diff --git a/feature/bgp/bmp/otg_tests/bmp_base_session_test/bmp_base_Session_test.go b/feature/bgp/bmp/otg_tests/bmp_base_session_test/bmp_base_Session_test.go new file mode 100644 index 00000000000..0d35578b64f --- /dev/null +++ b/feature/bgp/bmp/otg_tests/bmp_base_session_test/bmp_base_Session_test.go @@ -0,0 +1,610 @@ +package bmp_base_session_test + +import ( + "testing" + "time" + + "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/ygnmi/ygnmi" + "github.com/openconfig/ygot/ygot" + + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + otgtelemetry "github.com/openconfig/ondatra/gnmi/otg" +) + +const ( + dutAS = 64520 + ate1AS = 64530 + plenIPv4 = 30 + plenIPv6 = 126 + bmpStationPort = 7039 + prefix1v4 = "192.0.2.0" + prefix1v4Subnet = 24 + prefix2v4 = "172.16.0.0" + prefix2v4Subnet = 16 + prefix1v6 = "2002:db8:1::" + prefix1v6Subnet = 48 + prefix2v6 = "2001:db8::" + prefix2v6Subnet = 48 + routeCountV4 = 5000 + routeCountV6 = 5000 + bmpName = "atebmp" + prefixSet = "PREFIX-SET" + ipPrefixSet = "172.16.0.0/16" + prefixSubnetRange = "16..32" + prefixSetV6 = "PREFIX-SET-V6" + ipV6PrefixSet = "2001:db8::/32" + prefixV6SubnetRange = "32..128" + policyName = "BMP-POLICY" + prePolicyV4RouteCount = 10000 + prePolicyV6RouteCount = 10000 + postPolicyV4RouteCount = 9999 + postPolicyV6RouteCount = 5000 + timeout = 60 * time.Second +) + +type PolicyRoute struct { + Address string + PrefixLength int +} + +var ( + dutP1 = attrs.Attributes{ + Desc: "DUT to ATE Port 1", + IPv4: "193.0.2.1", + IPv6: "2002:db8:2::1", + MAC: "02:00:01:02:02:02", + IPv4Len: plenIPv4, + IPv6Len: plenIPv6, + } + + ateP1 = attrs.Attributes{ + Name: "atePort1", + IPv4: "193.0.2.2", + IPv6: "2002:db8:2::2", + MAC: "02:00:01:01:01:01", + IPv4Len: plenIPv4, + IPv6Len: plenIPv6, + } + + dutP2 = attrs.Attributes{ + Desc: "DUT to ATE Port 2", + IPv4: "193.0.3.1", + IPv6: "2002:db8:3::1", + MAC: "02:00:02:02:02:02", + IPv4Len: plenIPv4, + IPv6Len: plenIPv6, + } + + ateP2 = attrs.Attributes{ + Name: "atePort2", + IPv4: "193.0.3.2", + IPv6: "2002:db8:3::2", + MAC: "02:00:02:01:01:01", + IPv4Len: plenIPv4, + IPv6Len: plenIPv6, + } + + postPolicyRoutes = []PolicyRoute{ + { + Address: prefix1v4, + PrefixLength: prefix1v4Subnet, + }, + } + + postPolicyRoutesDenied = []PolicyRoute{ + { + Address: prefix2v4, + PrefixLength: prefix2v4Subnet, + }, + } + + prePolicyRoutes = []PolicyRoute{ + { + Address: prefix1v4, + PrefixLength: prefix1v4Subnet, + }, + { + Address: prefix2v4, + PrefixLength: prefix2v4Subnet, + }, + } + + postPolicyRoutesV6 = []PolicyRoute{ + { + Address: prefix1v6, + PrefixLength: prefix1v6Subnet, + }, + } + + postPolicyRoutesV6Denied = []PolicyRoute{ + { + Address: prefix2v6, + PrefixLength: prefix2v6Subnet, + }, + } + + prePolicyRoutesV6 = []PolicyRoute{ + { + Address: prefix1v6, + PrefixLength: prefix1v6Subnet, + }, + { + Address: prefix2v6, + PrefixLength: prefix2v6Subnet, + }, + } +) + +type ateConfigParams struct { + atePort gosnappi.Port + atePortAttrs attrs.Attributes + dutPortAttrs attrs.Attributes + ateAS uint32 + bmpName string + hostIPv4Start string + hostIPv6Start string +} + +// TestMain is the entry point for the test suite. +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +// configureDUT configures all DUT aspects. +func configureDUT(t *testing.T, dut *ondatra.DUTDevice) *gnmi.SetBatch { + t.Helper() + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + + bmpConfigParams := cfgplugins.BMPConfigParams{ + DutAS: dutAS, + Source: p2.Name(), + StationPort: bmpStationPort, + StationAddr: ateP2.IPv4, + } + + batch := &gnmi.SetBatch{} + gnmi.BatchReplace(batch, gnmi.OC().Interface(p1.Name()).Config(), dutP1.NewOCInterface(p1.Name(), dut)) + gnmi.BatchReplace(batch, gnmi.OC().Interface(p2.Name()).Config(), dutP2.NewOCInterface(p2.Name(), dut)) + cfgBGP := cfgplugins.BGPConfig{DutAS: dutAS, RouterID: dutP1.IPv4} + dutBgpConf := cfgplugins.ConfigureDUTBGP(t, dut, batch, cfgBGP) + configureDUTBGPNeighbors(t, dut, batch, dutBgpConf.Bgp) + cfgplugins.ConfigureBMP(t, dut, batch, bmpConfigParams) + batch.Set(t, dut) + fptest.ConfigureDefaultNetworkInstance(t, dut) + return batch +} + +func ptrToString(val string) *string { + return &val +} + +// configureDUTBGPNeighbors appends multiple BGP neighbor configurations to an existing BGP protocol on the DUT. Instead of calling AppendBGPNeighbor repeatedly in the test, this helper iterates over a slice of BGPNeighborConfig and applies each neighbor configuration into the given gnmi.SetBatch. +func configureDUTBGPNeighbors(t *testing.T, dut *ondatra.DUTDevice, batch *gnmi.SetBatch, bgp *oc.NetworkInstance_Protocol_Bgp) { + t.Helper() + // Add BGP neighbors + neighbors := []cfgplugins.BGPNeighborConfig{ + { + AteAS: ate1AS, + PortName: dutP1.Name, + NeighborIPv4: ateP1.IPv4, + NeighborIPv6: ateP1.IPv6, + IsLag: false, + PolicyName: ptrToString(policyName), + MultiPathEnabled: false, + }, + } + for _, n := range neighbors { + cfgplugins.AppendBGPNeighbor(t, dut, batch, bgp, n) + } + + rpl, err := configureBGPPolicy() + if err != nil { + t.Fatalf("Failed to configure BGP Policy: %v", err) + } + gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rpl) + +} + +func configureBGPPolicy() (*oc.RoutingPolicy, error) { + d := &oc.Root{} + rp := d.GetOrCreateRoutingPolicy() + pdef := rp.GetOrCreatePolicyDefinition(policyName) + + pset := rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(prefixSet) + pset.GetOrCreatePrefix(ipPrefixSet, prefixSubnetRange) + pset.SetMode(oc.PrefixSet_Mode_IPV4) + + stmt, err := pdef.AppendNewStatement("10") + if err != nil { + return nil, err + } + stmt.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_REJECT_ROUTE + stmt.GetOrCreateConditions().GetOrCreateMatchPrefixSet().PrefixSet = ygot.String(prefixSet) + + pset2 := rp.GetOrCreateDefinedSets().GetOrCreatePrefixSet(prefixSetV6) + pset2.SetMode(oc.PrefixSet_Mode_IPV6) + pset2.GetOrCreatePrefix(ipV6PrefixSet, prefixV6SubnetRange) + + stmt2, err := pdef.AppendNewStatement("20") + if err != nil { + return nil, err + } + stmt2.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_REJECT_ROUTE + stmt2.GetOrCreateConditions().GetOrCreateMatchPrefixSet().PrefixSet = ygot.String(prefixSetV6) + + stmt3, err := pdef.AppendNewStatement("30") + if err != nil { + return nil, err + } + stmt3.GetOrCreateActions().PolicyResult = oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE + + return rp, nil + +} + +// configureATE builds and returns the OTG configuration for the ATE topology. +func configureATE(t *testing.T, ate *ondatra.ATEDevice, bmpName string) gosnappi.Config { + t.Helper() + ateConfig := gosnappi.NewConfig() + + // Create ATE Ports + p1 := ate.Port(t, "port1") + p2 := ate.Port(t, "port2") + + // First, define OTG ports + atePort1 := ateConfig.Ports().Add().SetName(p1.ID()) + atePort2 := ateConfig.Ports().Add().SetName(p2.ID()) + + ateP1ConfigParams := ateConfigParams{ + atePort: atePort1, + atePortAttrs: ateP1, + dutPortAttrs: dutP1, + ateAS: ate1AS, + } + + ateP2ConfigParams := ateConfigParams{ + atePort: atePort2, + atePortAttrs: ateP2, + dutPortAttrs: dutP2, + bmpName: bmpName, + } + + // ATE Device 1 (EBGP) + configureBGPOnATEDevice(t, ateConfig, ateP1ConfigParams) + // ATE Device 2 (BMP) + configureBMPOnATEDevice(t, ateConfig, ateP2ConfigParams) + return ateConfig +} + +// configureATEDevice configures the ports along with the associated protocols. +func configureBGPOnATEDevice(t *testing.T, cfg gosnappi.Config, params ateConfigParams) { + t.Helper() + var peerTypeV4 gosnappi.BgpV4PeerAsTypeEnum + var peerTypeV6 gosnappi.BgpV6PeerAsTypeEnum + + dev := cfg.Devices().Add().SetName(params.atePortAttrs.Name) + eth := dev.Ethernets().Add().SetName(params.atePortAttrs.Name + "Eth").SetMac(params.atePortAttrs.MAC) + eth.Connection().SetPortName(params.atePort.Name()) + + ip4 := eth.Ipv4Addresses().Add().SetName(params.atePortAttrs.Name + ".IPv4") + ip4.SetAddress(params.atePortAttrs.IPv4).SetGateway(params.dutPortAttrs.IPv4).SetPrefix(uint32(params.atePortAttrs.IPv4Len)) + + ip6 := eth.Ipv6Addresses().Add().SetName(params.atePortAttrs.Name + ".IPv6") + ip6.SetAddress(params.atePortAttrs.IPv6).SetGateway(params.dutPortAttrs.IPv6).SetPrefix(uint32(params.atePortAttrs.IPv6Len)) + + bgp := dev.Bgp().SetRouterId(params.atePortAttrs.IPv4) + peerTypeV4 = gosnappi.BgpV4PeerAsType.EBGP + peerTypeV6 = gosnappi.BgpV6PeerAsType.EBGP + + bgpV4 := bgp.Ipv4Interfaces().Add().SetIpv4Name(ip4.Name()) + v4Peer := bgpV4.Peers().Add().SetName(params.atePortAttrs.Name + ".BGPv4.Peer").SetPeerAddress(params.dutPortAttrs.IPv4).SetAsNumber(params.ateAS).SetAsType(peerTypeV4) + + bgpV6 := bgp.Ipv6Interfaces().Add().SetIpv6Name(ip6.Name()) + v6Peer := bgpV6.Peers().Add().SetName(params.atePortAttrs.Name + ".BGPv6.Peer").SetPeerAddress(params.dutPortAttrs.IPv6).SetAsNumber(params.ateAS).SetAsType(peerTypeV6) + + // Advertise host routes + addBGPRoutes(v4Peer.V4Routes().Add(), params.atePortAttrs.Name+".Host.v4.1", prefix1v4, prefix1v4Subnet, routeCountV4, ip4.Address()) + addBGPRoutes(v6Peer.V6Routes().Add(), params.atePortAttrs.Name+".Host.v6.1", prefix1v6, prefix1v6Subnet, routeCountV6, ip6.Address()) + + addBGPRoutes(v4Peer.V4Routes().Add(), params.atePortAttrs.Name+".Host.v4.2", prefix2v4, prefix2v4Subnet, routeCountV4, ip4.Address()) + addBGPRoutes(v6Peer.V6Routes().Add(), params.atePortAttrs.Name+".Host.v6.2", prefix2v6, prefix2v6Subnet, routeCountV6, ip6.Address()) + +} + +// configureATEDevice configures the ports along with the associated protocols. +func configureBMPOnATEDevice(t *testing.T, cfg gosnappi.Config, params ateConfigParams) { + t.Helper() + + dev := cfg.Devices().Add().SetName(params.atePortAttrs.Name) + eth := dev.Ethernets().Add().SetName(params.atePortAttrs.Name + "Eth").SetMac(params.atePortAttrs.MAC) + eth.Connection().SetPortName(params.atePort.Name()) + + ip4 := eth.Ipv4Addresses().Add().SetName(params.atePortAttrs.Name + ".IPv4") + ip4.SetAddress(params.atePortAttrs.IPv4).SetGateway(params.dutPortAttrs.IPv4).SetPrefix(uint32(params.atePortAttrs.IPv4Len)) + + ip6 := eth.Ipv6Addresses().Add().SetName(params.atePortAttrs.Name + ".IPv6") + ip6.SetAddress(params.atePortAttrs.IPv6).SetGateway(params.dutPortAttrs.IPv6).SetPrefix(uint32(params.atePortAttrs.IPv6Len)) + + // --- BMP Configuration --- + bmpIntf := dev.Bmp().Ipv4Interfaces().Add() + bmpIntf.SetIpv4Name(ip4.Name()) //Name of the IPv4 intf on which you want to run BMP + bmpServer := bmpIntf.Servers().Add() + bmpServer.SetName(params.bmpName) + bmpServer.SetClientIp(params.dutPortAttrs.IPv4) // Connected reachable DUT IP + bmpServer.Connection().Passive().SetListenPort(bmpStationPort) // BMP port configured on DUT + + discard := bmpServer.PrefixStorage().Ipv4Unicast().Discard() + discard.Exceptions().Add(). + SetIpv4Prefix(prefix1v4). + SetPrefixLength(prefix1v4Subnet) + discard.Exceptions().Add(). + SetIpv4Prefix(prefix2v4). + SetPrefixLength(prefix2v4Subnet) + + discardv6 := bmpServer.PrefixStorage().Ipv6Unicast().Discard() + discardv6.Exceptions().Add(). + SetIpv6Prefix(prefix1v6). + SetPrefixLength(prefix1v6Subnet) + discardv6.Exceptions().Add(). + SetIpv6Prefix(prefix2v6). + SetPrefixLength(prefix2v6Subnet) + +} + +// addBGPRoutes adds BGP route advertisements to an ATE device. +func addBGPRoutes[R any](routes R, name, startAddress string, prefixLen, count uint32, nextHop string) { + switch r := any(routes).(type) { + case gosnappi.BgpV4RouteRange: + r.SetName(name).SetNextHopAddressType(gosnappi.BgpV4RouteRangeNextHopAddressType.IPV4).SetNextHopMode(gosnappi.BgpV4RouteRangeNextHopMode.MANUAL).SetNextHopIpv4Address(nextHop) + r.Addresses().Add().SetAddress(startAddress).SetPrefix(prefixLen).SetCount(count) + case gosnappi.BgpV6RouteRange: + r.SetName(name).SetNextHopAddressType(gosnappi.BgpV6RouteRangeNextHopAddressType.IPV6).SetNextHopMode(gosnappi.BgpV6RouteRangeNextHopMode.MANUAL).SetNextHopIpv6Address(nextHop) + r.Addresses().Add().SetAddress(startAddress).SetPrefix(prefixLen).SetCount(count) + } +} + +func verifyBMPSessionOnATE(t *testing.T, ate *ondatra.ATEDevice, bmpName string) { + t.Helper() + otg := ate.OTG() + + bmpServer := gnmi.OTG().BmpServer(bmpName) + + _, ok := gnmi.Watch(t, otg, bmpServer.SessionState().State(), 1*time.Minute, func(val *ygnmi.Value[otgtelemetry.E_BmpServer_SessionState]) bool { + state, ok := val.Val() + return ok && state == otgtelemetry.BmpServer_SessionState_UP + }).Await(t) + if !ok { + fptest.LogQuery(t, "ATE BMP session state", bmpServer.State(), gnmi.Get(t, otg, bmpServer.State())) + t.Fatalf("BMP Session state is not UP") + } + t.Log("BMP session is UP") +} + +func verifyBMPStatisticsReporting(t *testing.T, ate *ondatra.ATEDevice, bmpName string) { + t.Helper() + t.Log("Checking BMP statistics reporting on ATE before and after the interval") + + bmpServer := gnmi.OTG().BmpServer(bmpName) + + initialStatCounter := gnmi.Get(t, ate.OTG(), bmpServer.Counters().StatisticsMessagesReceived().State()) + t.Logf("Initial BMP statistics counter: %v", initialStatCounter) + + time.Sleep(60 * time.Second) + + updatedStatCounter := gnmi.Get(t, ate.OTG(), bmpServer.Counters().StatisticsMessagesReceived().State()) + t.Logf("Updated BMP statistics counter: %v", updatedStatCounter) + + if updatedStatCounter <= initialStatCounter { + t.Errorf("BMP statistics counter did not increment after 60 seconds. Initial: %v, Updated: %v", initialStatCounter, updatedStatCounter) + } else { + t.Log("BMP statistics counter incremented as expected.") + } +} + +func verifyBMPPostPolicyRouteMonitoring(t *testing.T, ate *ondatra.ATEDevice, bmpName string) { + t.Helper() + + otg := ate.OTG() + bmpServer := gnmi.OTG().BmpServer(bmpName) + + fptest.LogQuery(t, "Route Monitoring Updates", bmpServer.State(), gnmi.Get(t, otg, bmpServer.State())) + + prePolicyV4Routes := gnmi.Get(t, ate.OTG(), bmpServer.Counters().PrePolicyIpv4UnicastRoutesReceived().State()) + _, ok := gnmi.Watch(t, otg, bmpServer.Counters().PrePolicyIpv4UnicastRoutesReceived().State(), timeout, func(val *ygnmi.Value[uint64]) bool { + receiveState, present := val.Val() + return present && receiveState == prePolicyV4RouteCount + }).Await(t) + if !ok { + t.Fatalf("PrePolicyIpv4UnicastRoutesReceived did not match route counter") + } + t.Logf("PrePolicyRoutes: %v", prePolicyV4Routes) + + prePolicyV6Routes := gnmi.Get(t, ate.OTG(), bmpServer.Counters().PrePolicyIpv6UnicastRoutesReceived().State()) + _, ok = gnmi.Watch(t, otg, bmpServer.Counters().PrePolicyIpv6UnicastRoutesReceived().State(), timeout, func(val *ygnmi.Value[uint64]) bool { + receiveState, present := val.Val() + return present && receiveState == prePolicyV6RouteCount + }).Await(t) + if !ok { + t.Fatalf("PrePolicyIpv6UnicastRoutesReceived did not match route counter") + } + t.Logf("PrePolicyRoutes: %v", prePolicyV6Routes) + + postPolicyV4Routes := gnmi.Get(t, ate.OTG(), bmpServer.Counters().PostPolicyIpv4UnicastRoutesReceived().State()) + _, ok = gnmi.Watch(t, otg, bmpServer.Counters().PostPolicyIpv4UnicastRoutesReceived().State(), timeout, func(val *ygnmi.Value[uint64]) bool { + receiveState, present := val.Val() + return present && receiveState == postPolicyV4RouteCount + }).Await(t) + if !ok { + t.Fatalf("PostPolicyIpv4UnicastRoutesReceived did not match route counter") + } + t.Logf("PrePolicyRoutes: %v", postPolicyV4Routes) + + postPolicyV6Routes := gnmi.Get(t, ate.OTG(), bmpServer.Counters().PostPolicyIpv6UnicastRoutesReceived().State()) + _, ok = gnmi.Watch(t, otg, bmpServer.Counters().PostPolicyIpv6UnicastRoutesReceived().State(), timeout, func(val *ygnmi.Value[uint64]) bool { + receiveState, present := val.Val() + return present && receiveState == postPolicyV6RouteCount + }).Await(t) + if !ok { + t.Fatalf("PostPolicyIpv6UnicastRoutesReceived did not match route counter") + } + t.Logf("PrePolicyRoutes: %v", postPolicyV6Routes) +} + +func verifyBMPPostPolicyRouteMonitoringPerPrefix(t *testing.T, ate *ondatra.ATEDevice, bmpName string) { + t.Helper() + + path := gnmi.OTG().BmpServer(bmpName).PeerStateDatabase().PeerAny() + + for _, postPolicyRoute := range postPolicyRoutes { + _, ok := gnmi.WatchAll(t, ate.OTG(), path.PostPolicyInRib().BmpUnicastIpv4Prefix(postPolicyRoute.Address, uint32(postPolicyRoute.PrefixLength), 1, 0).State(), 2*time.Minute, func(v *ygnmi.Value[*otgtelemetry.BmpServer_PeerStateDatabase_Peer_PostPolicyInRib_BmpUnicastIpv4Prefix]) bool { + prefix, present := v.Val() + return present && prefix.GetAddress() == postPolicyRoute.Address + }).Await(t) + if !ok { + t.Errorf("postPolicyRoute %s not found in PostPolicyRib", postPolicyRoute.Address) + } + } + + for _, postPolicyRoutedenied := range postPolicyRoutesDenied { + _, ok := gnmi.WatchAll(t, ate.OTG(), path.PostPolicyInRib().BmpUnicastIpv4Prefix(postPolicyRoutedenied.Address, uint32(postPolicyRoutedenied.PrefixLength), 1, 0).State(), 10* time.Second, func(v *ygnmi.Value[*otgtelemetry.BmpServer_PeerStateDatabase_Peer_PostPolicyInRib_BmpUnicastIpv4Prefix]) bool { + prefix, present := v.Val() + return present && prefix.GetAddress() == postPolicyRoutedenied.Address + }).Await(t) + if ok { + t.Errorf("postPolicyDiscardRoute %s found in PostPolicyRib", postPolicyRoutedenied.Address) + } + } + + for _, prePolicyRoute := range prePolicyRoutes { + _, ok := gnmi.WatchAll(t, ate.OTG(), path.PrePolicyInRib().BmpUnicastIpv4Prefix(prePolicyRoute.Address, uint32(prePolicyRoute.PrefixLength), 1, 0).State(), 2*time.Minute, func(v *ygnmi.Value[*otgtelemetry.BmpServer_PeerStateDatabase_Peer_PrePolicyInRib_BmpUnicastIpv4Prefix]) bool { + prefix, present := v.Val() + return present && prefix.GetAddress() == prePolicyRoute.Address + }).Await(t) + if !ok { + t.Errorf("prePolicyRoute %s not found in PrePolicyRib", prePolicyRoute.Address) + } + } + + for _, postPolicyRoutev6 := range postPolicyRoutesV6 { + _, ok := gnmi.WatchAll(t, ate.OTG(), path.PostPolicyInRib().BmpUnicastIpv6Prefix(postPolicyRoutev6.Address, uint32(postPolicyRoutev6.PrefixLength), 1, 0).State(), 2*time.Minute, func(v *ygnmi.Value[*otgtelemetry.BmpServer_PeerStateDatabase_Peer_PostPolicyInRib_BmpUnicastIpv6Prefix]) bool { + prefix, present := v.Val() + return present && prefix.GetAddress() == postPolicyRoutev6.Address + }).Await(t) + if !ok { + t.Errorf("postPolicyRouteV6 %s not found in PostPolicyRib", postPolicyRoutev6.Address) + } + } + + for _, postPolicyRouteV6Denied := range postPolicyRoutesV6Denied { + _, ok := gnmi.WatchAll(t, ate.OTG(), path.PostPolicyInRib().BmpUnicastIpv4Prefix(postPolicyRouteV6Denied.Address, uint32(postPolicyRouteV6Denied.PrefixLength), 1, 0).State(), 10*time.Second, func(v *ygnmi.Value[*otgtelemetry.BmpServer_PeerStateDatabase_Peer_PostPolicyInRib_BmpUnicastIpv4Prefix]) bool { + prefix, present := v.Val() + return present && prefix.GetAddress() == postPolicyRouteV6Denied.Address + }).Await(t) + if ok { + t.Errorf("postPolicyDiscardRoute %s found in PostPolicyRib", postPolicyRouteV6Denied.Address) + } + } + + for _, prePolicyRoutev6 := range prePolicyRoutesV6 { + _, ok := gnmi.WatchAll(t, ate.OTG(), path.PrePolicyInRib().BmpUnicastIpv6Prefix(prePolicyRoutev6.Address, uint32(prePolicyRoutev6.PrefixLength), 1, 0).State(), 2*time.Minute, func(v *ygnmi.Value[*otgtelemetry.BmpServer_PeerStateDatabase_Peer_PrePolicyInRib_BmpUnicastIpv6Prefix]) bool { + prefix, present := v.Val() + return present && prefix.GetAddress() == prePolicyRoutev6.Address + }).Await(t) + if !ok { + t.Errorf("prePolicyRouteV6 %s not found in PrePolicyRib", prePolicyRoutev6.Address) + } + } +} + +func verifyPrefixCountV4(t *testing.T, dut *ondatra.DUTDevice) { + compare := func(val *ygnmi.Value[uint32]) bool { + c, ok := val.Val() + return ok && c == postPolicyV4RouteCount + } + statePath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Bgp() + prefixes := statePath.Neighbor(ateP1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Prefixes() + if got, ok := gnmi.Watch(t, dut, prefixes.Received().State(), 2*time.Minute, compare).Await(t); !ok { + t.Errorf("Received prefixes v4 mismatch: got %v, want %v", got, postPolicyV4RouteCount) + } +} + +func verifyPrefixCountV6(t *testing.T, dut *ondatra.DUTDevice) { + compare := func(val *ygnmi.Value[uint32]) bool { + c, ok := val.Val() + return ok && c == postPolicyV6RouteCount + } + statePath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Bgp() + prefixes := statePath.Neighbor(ateP1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Prefixes() + + if got, ok := gnmi.Watch(t, dut, prefixes.Received().State(), 2*time.Minute, compare).Await(t); !ok { + t.Errorf("Received prefixes v6 mismatch: got %v, want %v", got, postPolicyV6RouteCount) + } +} + +func TestBMPBaseSession(t *testing.T) { + dut := ondatra.DUT(t, "dut") + ate := ondatra.ATE(t, "ate") + + t.Log("Start DUT Configuration") + configureDUT(t, dut) + t.Log("Start ATE Configuration") + otgConfig := configureATE(t, ate, bmpName) + ate.OTG().PushConfig(t, otgConfig) + ate.OTG().StartProtocols(t) + + t.Log("Verify DUT BGP sessions up") + cfgplugins.VerifyDUTBGPEstablished(t, dut) + + t.Log("Verify OTG BGP sessions up") + cfgplugins.VerifyOTGBGPEstablished(t, ate) + + verifyPrefixCountV4(t, dut) + verifyPrefixCountV6(t, dut) + + type testCase struct { + name string + fn func(t *testing.T) + } + + cases := []testCase{ + { + name: "1.1.1_Verify_BMP_Session_Establishment", + fn: func(t *testing.T) { + + t.Log("Verify BMP session on ATE") + verifyBMPSessionOnATE(t, ate, bmpName) + }, + }, + { + name: "1.1.2_Verify_Statisitics_Reporting", + fn: func(t *testing.T) { + t.Log("Verify BMP session on DUT") + verifyBMPStatisticsReporting(t, ate, bmpName) + }, + }, + { + name: "1.1.3_Verify_Route_Monitoring_Post_Policy", + fn: func(t *testing.T) { + + t.Log("Verify Route Monitoring Post Policy on DUT") + verifyBMPPostPolicyRouteMonitoring(t, ate, bmpName) + verifyBMPPostPolicyRouteMonitoringPerPrefix(t, ate, bmpName) + }, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + tc.fn(t) + }) + } +} diff --git a/feature/bgp/bmp/otg_tests/bmp_base_session_test/metadata.textproto b/feature/bgp/bmp/otg_tests/bmp_base_session_test/metadata.textproto index 3ffd70bc00b..e418bfe3811 100644 --- a/feature/bgp/bmp/otg_tests/bmp_base_session_test/metadata.textproto +++ b/feature/bgp/bmp/otg_tests/bmp_base_session_test/metadata.textproto @@ -5,3 +5,13 @@ uuid: "ae321451-e937-4f99-885d-bec2bf616702" plan_id: "BMP-1.1" description: "BMP Session Establishment and Telemetry Test" testbed: TESTBED_DUT_ATE_2LINKS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + bmp_oc_unsupported: true + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index b910a5a38f2..99514329b5b 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,10 @@ module github.com/openconfig/featureprofiles go 1.24.7 +replace github.com/open-traffic-generator/snappi/gosnappi => github.com/open-traffic-generator/snappi/gosnappi v1.41.1-0.20251117102858-c0e8e2643864 + +replace github.com/openconfig/ondatra => github.com/open-traffic-generator/ondatra v0.0.0-20251202080245-3553b048b900 + require ( cloud.google.com/go/pubsub v1.45.1 cloud.google.com/go/storage v1.49.0 @@ -15,13 +19,14 @@ require ( github.com/google/uuid v1.6.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/kr/pretty v0.3.1 - github.com/open-traffic-generator/snappi/gosnappi v1.40.0 + github.com/open-traffic-generator/snappi/gosnappi v1.42.0 github.com/openconfig/containerz v0.0.0-20250408205203-029560584812 github.com/openconfig/entity-naming v0.0.0-20250108173956-784f643e8b64 github.com/openconfig/functional-translators v0.0.0-20250923103542-4bd20e7e0ef0 github.com/openconfig/gnmi v0.14.1 github.com/openconfig/gnoi v0.7.0 github.com/openconfig/gnoigo v0.0.0-20250918224707-fee0fe3eee56 + github.com/openconfig/gnpsi v0.3.2 github.com/openconfig/gnsi v1.9.0 github.com/openconfig/gocloser v0.0.0-20250211195114-79e08bd41eef github.com/openconfig/goyang v1.6.3 @@ -42,12 +47,12 @@ require ( github.com/spf13/viper v1.21.0 github.com/yoheimuta/go-protoparser/v4 v4.9.0 github.com/yuin/goldmark v1.4.13 - golang.org/x/crypto v0.42.0 + golang.org/x/crypto v0.44.0 golang.org/x/exp v0.0.0-20250911091902-df9299821621 - golang.org/x/text v0.29.0 + golang.org/x/text v0.31.0 google.golang.org/api v0.215.0 - google.golang.org/grpc v1.75.1 - google.golang.org/protobuf v1.36.9 + google.golang.org/grpc v1.77.0 + google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/klog/v2 v2.130.1 @@ -56,7 +61,7 @@ require ( require ( github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - golang.org/x/oauth2 v0.30.0 + golang.org/x/oauth2 v0.32.0 ) require ( @@ -65,11 +70,11 @@ require ( cloud.google.com/go v0.116.0 // indirect cloud.google.com/go/auth v0.13.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect - cloud.google.com/go/compute/metadata v0.7.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/monitoring v1.21.2 // indirect dario.cat/mergo v1.0.0 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect github.com/ProtonMail/go-crypto v1.1.3 // indirect @@ -79,21 +84,21 @@ require ( github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect - github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect + github.com/cncf/xds/go v0.0.0-20251022180443-0feb69152e9f // indirect github.com/creack/pty v1.1.18 // indirect github.com/cyphar/filepath-securejoin v0.2.5 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/drivenets/cdnos-controller v1.7.4 // indirect github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.35.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -109,7 +114,7 @@ require ( github.com/google/s2a-go v0.1.8 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect @@ -129,7 +134,6 @@ require ( github.com/open-traffic-generator/keng-operator v0.3.28 // indirect github.com/openconfig/attestz v0.5.0 // indirect github.com/openconfig/bootz v0.6.0 // indirect - github.com/openconfig/gnpsi v0.3.2 // indirect github.com/openconfig/grpctunnel v0.1.0 // indirect github.com/openconfig/lemming/operator v0.2.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect @@ -146,15 +150,14 @@ require ( github.com/skeema/knownhosts v1.3.0 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect - github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/srl-labs/srl-controller v0.6.1 // indirect github.com/srl-labs/srlinux-scrapli v0.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/zeebo/errs v1.4.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.38.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect @@ -165,17 +168,17 @@ require ( go.opentelemetry.io/otel/sdk v1.38.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect - go.opentelemetry.io/proto/otlp v1.8.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.44.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/term v0.35.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect golang.org/x/time v0.9.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250922171735-9219d122eba9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251124214823-79d6a2a48846 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index 78aeb0c4323..7463af5a273 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= -cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= -cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= cloud.google.com/go/kms v1.20.1 h1:og29Wv59uf2FVaZlesaiDAqHFzHaoUyHI3HYp9VUHVg= @@ -31,8 +31,8 @@ cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgY dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.48.1 h1:oTX4vsorBZo/Zdum6OKPA4o7544hm6smoRv1QjpTwGo= @@ -76,8 +76,8 @@ github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= -github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20251022180443-0feb69152e9f h1:Y8xYupdHxryycyPlc9Y+bSQAYZnetRJ70VMVKm5CKI0= +github.com/cncf/xds/go v0.0.0-20251022180443-0feb69152e9f/go.mod h1:HlzOvOjVBOfTGSRXRyY0OiCS/3J1akRGQQpRO/7zyF4= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -108,10 +108,10 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= -github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= -github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= -github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane v0.13.5-0.20251024222203-75eaa193e329 h1:K+fnvUM0VZ7ZFJf0n4L/BRlnsb9pL/GuDG6FqaH+PwM= +github.com/envoyproxy/go-control-plane v0.13.5-0.20251024222203-75eaa193e329/go.mod h1:Alz8LEClvR7xKsrq3qzoc4N0guvVNSS8KmSChGYr9hs= +github.com/envoyproxy/go-control-plane/envoy v1.35.0 h1:ixjkELDE+ru6idPxcHLj8LBVc2bFP7iBytj353BoHUo= +github.com/envoyproxy/go-control-plane/envoy v1.35.0/go.mod h1:09qwbGVuSWWAyN5t/b3iyVfz5+z8QWGrzkoqm/8SbEs= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -140,8 +140,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -229,8 +229,8 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/h-fam/errdiff v1.0.2 h1:rPsW4ob2fMOIulwTEoZXaaUIuud7XUudw5SLKTZj3Ss= github.com/h-fam/errdiff v1.0.2/go.mod h1:FOzgnHXSEE3rRvmGXgmiqWl+H3lwLywYm9CSXqXrSTg= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= @@ -293,8 +293,10 @@ github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/open-traffic-generator/keng-operator v0.3.28 h1:FpDe1wtGODN7ByAhF2LxMIlbDqb5yVmbSE5Y49nyc28= github.com/open-traffic-generator/keng-operator v0.3.28/go.mod h1:+koaOnSyrJHdzxnaye+M6k+ZbszQlWI9u3tMxSpORNA= -github.com/open-traffic-generator/snappi/gosnappi v1.40.0 h1:nozIcqUsmN771mm6d2SR9C6tB4euoUHMxIl1+CqE7PE= -github.com/open-traffic-generator/snappi/gosnappi v1.40.0/go.mod h1:Dyc7iaSc6HtMJscClMr+wCPTwWHGxv7Htw4ZoGn2kFI= +github.com/open-traffic-generator/ondatra v0.0.0-20251202080245-3553b048b900 h1:b/STwSXOlcJ1VcjeKldP2RxWtJ9MTlxCjgBcx84Pv8Q= +github.com/open-traffic-generator/ondatra v0.0.0-20251202080245-3553b048b900/go.mod h1:ipik+TR7ggG4FPly2aUQ6VB5PYzeYHhJDkbIcXvKnJI= +github.com/open-traffic-generator/snappi/gosnappi v1.41.1-0.20251117102858-c0e8e2643864 h1:zYykyRR67rO8WcifwxNrhR39aoiXmHVw75wTWl1E/yY= +github.com/open-traffic-generator/snappi/gosnappi v1.41.1-0.20251117102858-c0e8e2643864/go.mod h1:YLr6kzoy7ryuoM3ZFaPZmfAvyx6O7o0LYvLieczgiA0= github.com/openconfig/attestz v0.5.0 h1:1XDcw8CaAxS9+Yrrmj69qChwa2Y5q/TlcU9h4up3Qrc= github.com/openconfig/attestz v0.5.0/go.mod h1:b4sZBEyj054i4TKG1iB/ZQXMvz/15KDSDmhGVANYD9g= github.com/openconfig/bootz v0.6.0 h1:QAbYVKKYqoJfO7Vzmv4PTBTcPe1PWRrSz0vgALvnYdk= @@ -333,8 +335,6 @@ github.com/openconfig/lemming/operator v0.2.0 h1:dovZnR6lQkOHXcODli1NDOr/GVYrBY0 github.com/openconfig/lemming/operator v0.2.0/go.mod h1:LKgEXSR5VK2CAeh2uKijKAXFj42uQuwakrCHVPF0iII= github.com/openconfig/models-ci v1.0.2-0.20231113233730-f0986391428e h1:6N4jXpZa/SXYcNpJFjjZvenxO/xnTwuUCgCEinhNLfU= github.com/openconfig/models-ci v1.0.2-0.20231113233730-f0986391428e/go.mod h1:w38G/kObu95PbtwMYVp6SKhkHCegJFwL8B58Ns84g4s= -github.com/openconfig/ondatra v0.12.3 h1:C5P6iRZ6DQRvUPg+JAUIcMJXctxHesIi1GvqeyfCSoA= -github.com/openconfig/ondatra v0.12.3/go.mod h1:nwDBKm/soMSoFb6Z/U2YNYj0jbLBUwvA936AcoEEs5w= github.com/openconfig/replayer v0.0.0-20240110192655-4e9cf83d8d30 h1:KcHS08m7nFHq/D03ZfZKKNCSaS1jsuvdF3lCyDjPWJc= github.com/openconfig/replayer v0.0.0-20240110192655-4e9cf83d8d30/go.mod h1:VQ8FdPVaHwxKtamhcrwkPsvTeeoEgFYNK1xE8nHD0S8= github.com/openconfig/testt v0.0.0-20220311054427-efbb1a32ec07 h1:X631iD/B0ximGFb5P9LY5wHju4SiedxUhc5UZEo7VSw= @@ -368,8 +368,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= @@ -412,8 +412,8 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= -github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/srl-labs/srl-controller v0.6.1 h1:hHduqG41wglpeVPD85RALTwWWcS+NqvU8V1pHJMQIZo= github.com/srl-labs/srl-controller v0.6.1/go.mod h1:PedxdPZPtDcC+wDOKhG6uXR4xgkHxb4JhW1cXNk/eaY= github.com/srl-labs/srlinux-scrapli v0.6.0 h1:YQjckD+a7f6u2M+k4SmJUrDa7BFvoOTb2mMbPe6hLZM= @@ -450,16 +450,14 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= -github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= go.einride.tech/aip v0.68.0 h1:4seM66oLzTpz50u4K1zlJyOXQ3tCzcJN7I22tKkjipw= go.einride.tech/aip v0.68.0/go.mod h1:7y9FF8VtPWqpxuAxl0KQWqaULxW4zFIesD6zF5RIHHg= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= -go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= +go.opentelemetry.io/contrib/detectors/gcp v1.38.0 h1:ZoYbqX7OaA/TAikspPl3ozPI6iY6LiIY9I8cUfm+pJs= +go.opentelemetry.io/contrib/detectors/gcp v1.38.0/go.mod h1:SU+iU7nu5ud4oCb3LQOhIZ3nRLj6FNVrKgtflbaf2ts= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= @@ -483,8 +481,8 @@ go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689Cbtr go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.8.0 h1:fRAZQDcAFHySxpJ1TwlA1cJ4tvcrw7nXl9xWWC8N5CE= -go.opentelemetry.io/proto/otlp v1.8.0/go.mod h1:tIeYOeNBU4cvmPqpaji1P+KbB4Oloai8wN4rWzRrFF0= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -506,8 +504,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= @@ -537,12 +535,12 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -550,8 +548,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -571,22 +569,22 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -600,8 +598,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -622,10 +620,10 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= -google.golang.org/genproto/googleapis/api v0.0.0-20250922171735-9219d122eba9 h1:jm6v6kMRpTYKxBRrDkYAitNJegUeO1Mf3Kt80obv0gg= -google.golang.org/genproto/googleapis/api v0.0.0-20250922171735-9219d122eba9/go.mod h1:LmwNphe5Afor5V3R5BppOULHOnt2mCIf+NxMd4XiygE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/api v0.0.0-20251124214823-79d6a2a48846 h1:ZdyUkS9po3H7G0tuh955QVyyotWvOD4W0aEapeGeUYk= +google.golang.org/genproto/googleapis/api v0.0.0-20251124214823-79d6a2a48846/go.mod h1:Fk4kyraUvqD7i5H6S43sj2W98fbZa75lpZz/eUyhfO0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 h1:Wgl1rcDNThT+Zn47YyCXOXyX/COgMTIdhJ717F0l4xk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -635,8 +633,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -649,8 +647,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/cfgplugins/bgp.go b/internal/cfgplugins/bgp.go index 3dea888abae..feaa94de2b1 100644 --- a/internal/cfgplugins/bgp.go +++ b/internal/cfgplugins/bgp.go @@ -172,6 +172,8 @@ type BGPConfig struct { ECMPMaxPath uint32 // RouterID is the router ID of the DUT. (Usually the IPv4 address.) RouterID string + // MaxPath + EnableMaxPath bool } // BGPNeighborConfig holds params for creating BGP neighbors + peer groups. @@ -182,6 +184,18 @@ type BGPNeighborConfig struct { NeighborIPv6 string IsLag bool MultiPathEnabled bool + PolicyName *string +} + +type BMPConfigParams struct { + DutAS uint32 + AteAS uint32 + BGPObj *oc.NetworkInstance_Protocol_Bgp + Source string + LocalAddr string + StationAddr string + StationPort uint16 + StatsTimeOut uint16 } // BgpNeighborScale holds parameters for configuring BGP neighbors in a scale test. @@ -854,9 +868,10 @@ func ConfigureDUTBGP(t *testing.T, dut *ondatra.DUTDevice, batch *gnmi.SetBatch, af6.Enabled = ygot.Bool(true) // Handle multipath deviation - if deviations.MultipathUnsupportedNeighborOrAfisafi(dut) { - t.Log("Executing CLI commands for multipath deviation") - bgpRouteConfig := fmt.Sprintf(` + if cfg.EnableMaxPath { + if deviations.MultipathUnsupportedNeighborOrAfisafi(dut) { + t.Log("Executing CLI commands for multipath deviation") + bgpRouteConfig := fmt.Sprintf(` router bgp %d address-family ipv4 maximum-paths %[2]d ecmp %[2]d @@ -865,23 +880,24 @@ func ConfigureDUTBGP(t *testing.T, dut *ondatra.DUTDevice, batch *gnmi.SetBatch, maximum-paths %[2]d ecmp %[2]d bgp bestpath as-path multipath-relax `, cfg.DutAS, cfg.ECMPMaxPath) - helpers.GnmiCLIConfig(t, dut, bgpRouteConfig) - } else { - // TODO: Once multipath is fully supported via OpenConfig across all platforms, - // remove CLI fallback and rely solely on OC configuration. - v4Multipath := af4.GetOrCreateUseMultiplePaths() - v4Multipath.SetEnabled(true) - v4Multipath.GetOrCreateIbgp().SetMaximumPaths(cfg.ECMPMaxPath) - v4Multipath.GetOrCreateEbgp().SetMaximumPaths(cfg.ECMPMaxPath) - - v6Multipath := af6.GetOrCreateUseMultiplePaths() - v6Multipath.SetEnabled(true) - v6Multipath.GetOrCreateIbgp().SetMaximumPaths(cfg.ECMPMaxPath) - v6Multipath.GetOrCreateEbgp().SetMaximumPaths(cfg.ECMPMaxPath) - - if !deviations.SkipSettingAllowMultipleAS(dut) { - v4Multipath.GetOrCreateEbgp().SetAllowMultipleAs(true) - v6Multipath.GetOrCreateEbgp().SetAllowMultipleAs(true) + helpers.GnmiCLIConfig(t, dut, bgpRouteConfig) + } else { + // TODO: Once multipath is fully supported via OpenConfig across all platforms, + // remove CLI fallback and rely solely on OC configuration. + v4Multipath := af4.GetOrCreateUseMultiplePaths() + v4Multipath.SetEnabled(true) + v4Multipath.GetOrCreateIbgp().SetMaximumPaths(cfg.ECMPMaxPath) + v4Multipath.GetOrCreateEbgp().SetMaximumPaths(cfg.ECMPMaxPath) + + v6Multipath := af6.GetOrCreateUseMultiplePaths() + v6Multipath.SetEnabled(true) + v6Multipath.GetOrCreateIbgp().SetMaximumPaths(cfg.ECMPMaxPath) + v6Multipath.GetOrCreateEbgp().SetMaximumPaths(cfg.ECMPMaxPath) + + if !deviations.SkipSettingAllowMultipleAS(dut) { + v4Multipath.GetOrCreateEbgp().SetAllowMultipleAs(true) + v6Multipath.GetOrCreateEbgp().SetAllowMultipleAs(true) + } } } gnmi.BatchUpdate(batch, dutBgpConfPath.Config(), dutBgpConf) @@ -899,8 +915,13 @@ func AppendBGPNeighbor(t *testing.T, dut *ondatra.DUTDevice, batch *gnmi.SetBatc pgafv4 := pgv4.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST) pgafv4.Enabled = ygot.Bool(true) rpl4 := pgafv4.GetOrCreateApplyPolicy() - rpl4.ImportPolicy = []string{ALLOW} - rpl4.ExportPolicy = []string{ALLOW} + if cfg.PolicyName != nil { + rpl4.ImportPolicy = []string{*cfg.PolicyName} + rpl4.ExportPolicy = []string{*cfg.PolicyName} + } else { + rpl4.ImportPolicy = []string{ALLOW} + rpl4.ExportPolicy = []string{ALLOW} + } // === Peer Group for IPv6 === pgv6Name := cfg.PortName + "BGP-PEER-GROUP-V6" @@ -910,8 +931,13 @@ func AppendBGPNeighbor(t *testing.T, dut *ondatra.DUTDevice, batch *gnmi.SetBatc pgafv6 := pgv6.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST) pgafv6.Enabled = ygot.Bool(true) rpl6 := pgafv6.GetOrCreateApplyPolicy() - rpl6.ImportPolicy = []string{ALLOW} - rpl6.ExportPolicy = []string{ALLOW} + if cfg.PolicyName != nil { + rpl6.ImportPolicy = []string{*cfg.PolicyName} + rpl6.ExportPolicy = []string{*cfg.PolicyName} + } else { + rpl6.ImportPolicy = []string{ALLOW} + rpl6.ExportPolicy = []string{ALLOW} + } if cfg.MultiPathEnabled { if deviations.MultipathUnsupportedNeighborOrAfisafi(dut) { @@ -1573,3 +1599,43 @@ func VerifyRoutes(t *testing.T, dut *ondatra.DUTDevice, routesToAdvertise map[st } } } + +// ConfigureBMP applies BMP station configuration on DUT. +func ConfigureBMP(t *testing.T, dut *ondatra.DUTDevice, batch *gnmi.SetBatch, cfgParams BMPConfigParams) { + t.Helper() + if deviations.BMPOCUnsupported(dut) { + t.Log("Executing CLI commands for multipath deviation") + // TODO: change the below constants + BMPRouteConfig := fmt.Sprintf(` + router bgp %[1]d + neighbor BGP-PEER-GROUP-V4 maximum-routes 0 + neighbor BGP-PEER-GROUP-V6 maximum-routes 0 + bgp monitoring + ! BMP station + monitoring station BMP_STN1 + update-source %s + statistics + connection address %s + connection mode active port %d + `, cfgParams.DutAS, cfgParams.Source, cfgParams.StationAddr, cfgParams.StationPort) + helpers.GnmiCLIConfig(t, dut, BMPRouteConfig) + } else { + // TODO: BMP support is not yet available, so the code below is commented out and will be enabled once BMP is implemented. + t.Log("BMP support is not yet available, so the code below is commented out and will be enabled once BMP is implemented.") + // // === BMP Configuration === + // bmp := cfgParams.BGPObj.Global.GetOrCreateBmp() + // bmp.LocalAddress = ygot.String(cfgParams.LocalAddr) + // bmp.StatisticsTimeout = ygot.Uint16(cfgParams.StatsTimeOut) + + // // --- Create BMP Station --- + // st := bmp.GetOrCreateStation("BMP_STN1") + // st.Address = ygot.String(cfgParams.StationAddr) + // st.Port = ygot.Uint16(cfgParams.StationPort) + // st.ConnectionMode = oc.BgpTypes_BMPStationMode_ACTIVE + // st.Description = ygot.String("ATE BMP station") + // st.PolicyType = oc.BgpTypes_BMPPolicyType_POST_POLICY + // st.ExcludeNoneligible = ygot.Bool(true) + // // Push configuration + // gnmi.BatchUpdate(batch, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").Config(), bmp) + } +} diff --git a/internal/deviations/deviations.go b/internal/deviations/deviations.go index 0ac85de42e5..c647276af59 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -1768,3 +1768,7 @@ func GnpsiOcUnsupported(dut *ondatra.DUTDevice) bool { func SyslogNonDefaultVrfUnsupported(dut *ondatra.DUTDevice) bool { return lookupDUTDeviations(dut).GetSyslogNonDefaultVrfUnsupported() } + +func BMPOCUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetBmpOcUnsupported() +} diff --git a/proto/metadata.proto b/proto/metadata.proto index cfd3c61a44b..308fb71c4eb 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -1041,9 +1041,12 @@ message Metadata { // Cisco: b/455784294 bool bgp_graceful_restart_under_afi_safi_unsupported = 350; + // Arista https://partnerissuetracker.corp.google.com/issues/452484903 + bool bmp_oc_unsupported = 351; + // Device does not support adding remote-syslog config under non-default VRF // Cisco: https://partnerissuetracker.corp.google.com/u/0/issues/459659437 - bool syslog_non_default_vrf_unsupported = 351; + bool syslog_non_default_vrf_unsupported = 352; // 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; diff --git a/proto/metadata_go_proto/metadata.pb.go b/proto/metadata_go_proto/metadata.pb.go index d9445416bcf..1471c44b553 100644 --- a/proto/metadata_go_proto/metadata.pb.go +++ b/proto/metadata_go_proto/metadata.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.10 -// protoc v6.32.1 +// protoc-gen-go v1.36.6 +// protoc v6.33.0 // source: metadata.proto package metadata_go_proto @@ -1228,9 +1228,11 @@ type Metadata_Deviations struct { // Device does not support bgp GR-RESTART under AFI/SAFI. // Cisco: b/455784294 BgpGracefulRestartUnderAfiSafiUnsupported bool `protobuf:"varint,350,opt,name=bgp_graceful_restart_under_afi_safi_unsupported,json=bgpGracefulRestartUnderAfiSafiUnsupported,proto3" json:"bgp_graceful_restart_under_afi_safi_unsupported,omitempty"` + // Arista https://partnerissuetracker.corp.google.com/issues/452484903 + BmpOcUnsupported bool `protobuf:"varint,351,opt,name=bmp_oc_unsupported,json=bmpOcUnsupported,proto3" json:"bmp_oc_unsupported,omitempty"` // Device does not support adding remote-syslog config under non-default VRF // Cisco: https://partnerissuetracker.corp.google.com/u/0/issues/459659437 - SyslogNonDefaultVrfUnsupported bool `protobuf:"varint,351,opt,name=syslog_non_default_vrf_unsupported,json=syslogNonDefaultVrfUnsupported,proto3" json:"syslog_non_default_vrf_unsupported,omitempty"` + SyslogNonDefaultVrfUnsupported bool `protobuf:"varint,352,opt,name=syslog_non_default_vrf_unsupported,json=syslogNonDefaultVrfUnsupported,proto3" json:"syslog_non_default_vrf_unsupported,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3484,6 +3486,13 @@ func (x *Metadata_Deviations) GetBgpGracefulRestartUnderAfiSafiUnsupported() boo return false } +func (x *Metadata_Deviations) GetBmpOcUnsupported() bool { + if x != nil { + return x.BmpOcUnsupported + } + return false +} + func (x *Metadata_Deviations) GetSyslogNonDefaultVrfUnsupported() bool { if x != nil { return x.SyslogNonDefaultVrfUnsupported @@ -3547,7 +3556,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\"\xcd\xc1\x01\n" + + "\x0emetadata.proto\x12\x12openconfig.testing\x1a1github.com/openconfig/ondatra/proto/testbed.proto\"\xfc\xc1\x01\n" + "\bMetadata\x12\x12\n" + "\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x17\n" + "\aplan_id\x18\x02 \x01(\tR\x06planId\x12 \n" + @@ -3559,7 +3568,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ַ\x01\n" + + "\x16software_version_regex\x18\x04 \x01(\tR\x14softwareVersionRegexJ\x04\b\x02\x10\x03R\x0ehardware_model\x1a\x85\xb8\x01\n" + "\n" + "Deviations\x120\n" + "\x14ipv4_missing_enabled\x18\x01 \x01(\bR\x12ipv4MissingEnabled\x129\n" + @@ -3881,8 +3890,9 @@ const file_metadata_proto_rawDesc = "" + "1static_route_next_network_instance_oc_unsupported\x18\xdb\x02 \x01(\bR+staticRouteNextNetworkInstanceOcUnsupported\x121\n" + "\x14gnpsi_oc_unsupported\x18\xdc\x02 \x01(\bR\x12gnpsiOcUnsupported\x12I\n" + "!bgp_gr_helper_disable_unsupported\x18\xdd\x02 \x01(\bR\x1dbgpGrHelperDisableUnsupported\x12c\n" + - "/bgp_graceful_restart_under_afi_safi_unsupported\x18\xde\x02 \x01(\bR)bgpGracefulRestartUnderAfiSafiUnsupported\x12K\n" + - "\"syslog_non_default_vrf_unsupported\x18\xdf\x02 \x01(\bR\x1esyslogNonDefaultVrfUnsupportedJ\x04\bT\x10UJ\x04\b\t\x10\n" + + "/bgp_graceful_restart_under_afi_safi_unsupported\x18\xde\x02 \x01(\bR)bgpGracefulRestartUnderAfiSafiUnsupported\x12-\n" + + "\x12bmp_oc_unsupported\x18\xdf\x02 \x01(\bR\x10bmpOcUnsupported\x12K\n" + + "\"syslog_non_default_vrf_unsupported\x18\xe0\x02 \x01(\bR\x1esyslogNonDefaultVrfUnsupportedJ\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\x02\x1a\xa0\x01\n" + "\x12PlatformExceptions\x12A\n" + "\bplatform\x18\x01 \x01(\v2%.openconfig.testing.Metadata.PlatformR\bplatform\x12G\n" +