diff --git a/Makefile b/Makefile index f8c073bb..f13b3acc 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,10 @@ buildfile: bazel run //:gazelle -- update-repos -to_macro=repositories.bzl%go_repositories -from_file=go.mod bazel run //:gazelle +.PHONY: genprotos +genprotos: + tools/genproto.sh + .PHONY: load-debug load-debug: DOCKER_BUILDKIT=1 docker build . --target debug -f Dockerfile.lemming -t "us-west1-docker.pkg.dev/openconfig-lemming/release/lemming:ga" diff --git a/bgp/gobgp.go b/bgp/gobgp.go index 9879547f..bcb2eb89 100644 --- a/bgp/gobgp.go +++ b/bgp/gobgp.go @@ -134,7 +134,9 @@ func (t *bgpDeclTask) startGoBGPFuncDecl(_ context.Context, yclient *ygnmi.Clien BGPPath.NeighborAny().PeerAs().Config().PathStruct(), BGPPath.NeighborAny().NeighborAddress().Config().PathStruct(), BGPPath.NeighborAny().NeighborPort().Config().PathStruct(), + BGPPath.NeighborAny().Transport().LocalAddress().Config().PathStruct(), // BGP Policy statements + RoutingPolicyPath.PolicyDefinitionAny().Name().Config().PathStruct(), RoutingPolicyPath.PolicyDefinitionAny().StatementMap().Config().PathStruct(), BGPPath.NeighborAny().ApplyPolicy().DefaultImportPolicy().Config().PathStruct(), BGPPath.NeighborAny().ApplyPolicy().DefaultExportPolicy().Config().PathStruct(), @@ -236,7 +238,9 @@ func (t *bgpDeclTask) startGoBGPFuncDecl(_ context.Context, yclient *ygnmi.Clien }, func(d *api.Destination) { log.V(1).Infof("%s: GoBGP global table path: %v", t.targetName, d) }); err != nil { - log.Errorf("GoBGP ListPath call failed (global table): %v", err) + if err.Error() != "bgp server hasn't started yet" { + log.Errorf("GoBGP ListPath call failed (global table): %v", err) + } } else { log.V(1).Info("GoBGP ListPath call completed (global table)") } @@ -255,7 +259,7 @@ func (t *bgpDeclTask) startGoBGPFuncDecl(_ context.Context, yclient *ygnmi.Clien // TODO: For locally-originated routes figure out how to get the originating protocol. origin = oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_UNSET } else { - origin = oc.UnionString(path.SourceId) + origin = oc.UnionString(path.NeighborIp) } // TODO: this ID should match the ID in adj-rib-in-post. locRib.GetOrCreateRoute(route.Prefix, origin, uint32(j)) @@ -272,6 +276,7 @@ func (t *bgpDeclTask) startGoBGPFuncDecl(_ context.Context, yclient *ygnmi.Clien t.queryTable(neigh, "adj-rib-in", api.TableType_ADJ_IN, func(routes []*api.Destination) { for _, route := range routes { for j, path := range route.Paths { + // TODO: this ID should be retrieved from the update message. neighContainer.GetOrCreateAdjRibInPre().GetOrCreateRoute(route.Prefix, uint32(j)) if !path.Filtered { neighContainer.GetOrCreateAdjRibInPost().GetOrCreateRoute(route.Prefix, uint32(j)) @@ -325,7 +330,9 @@ func (t *bgpDeclTask) queryTable(neighbor, tableName string, tableType api.Table routes = append(routes, d) log.V(0).Infof("%s: GoBGP %s table path (neighbor if applicable: %q): %v", t.targetName, tableName, neighbor, d) }); err != nil { - log.Errorf("GoBGP ListPath call failed (%s table): %v", tableType, err) + if err.Error() != "bgp server hasn't started yet" { + log.Errorf("GoBGP ListPath call failed (%s table): %v", tableType, err) + } } else { log.V(1).Info("GoBGP ListPath call completed (%s table)", tableName) f(routes) @@ -390,9 +397,10 @@ func intendedToGoBGP(bgpoc *oc.NetworkInstance_Protocol_Bgp, policyoc *oc.Routin bgpConfig.Global.Config.RouterId = global.GetRouterId() bgpConfig.Global.Config.Port = int32(listenPort) - localAddress := "" if localAddr, err := netip.ParseAddr(global.GetRouterId()); err == nil && localAddr.IsLoopback() { - localAddress = localAddr.String() + // Have GoBGP listen only on local address instead of all + // addresses when testing BGP server on localhost. + bgpConfig.Global.Config.LocalAddressList = []string{localAddr.String()} } for neighAddr, neigh := range bgpoc.Neighbor { @@ -415,7 +423,7 @@ func intendedToGoBGP(bgpoc *oc.NetworkInstance_Protocol_Bgp, policyoc *oc.Routin }, Transport: bgpconfig.Transport{ Config: bgpconfig.TransportConfig{ - LocalAddress: localAddress, + LocalAddress: neigh.GetTransport().GetLocalAddress(), RemotePort: neigh.GetNeighborPort(), }, }, diff --git a/bgp/tests/local_tests/community_set_test.go b/bgp/tests/local_tests/community_set_test.go index 76cadf26..d8270b90 100644 --- a/bgp/tests/local_tests/community_set_test.go +++ b/bgp/tests/local_tests/community_set_test.go @@ -21,7 +21,6 @@ import ( "github.com/openconfig/lemming/bgp" "github.com/openconfig/lemming/gnmi/oc" "github.com/openconfig/lemming/gnmi/oc/ocpath" - "github.com/openconfig/ygnmi/ygnmi" valpb "github.com/openconfig/lemming/bgp/tests/proto/policyval" ) @@ -43,16 +42,18 @@ func TestCommunitySet(t *testing.T) { Input: &valpb.TestRoute{ ReachPrefix: "10.33.0.0/16", }, - ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_DISCARD, + ExpectedResultBeforePolicy: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, + ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_DISCARD, }, { Description: "Accepted route", Input: &valpb.TestRoute{ ReachPrefix: "10.3.0.0/16", }, - ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, + ExpectedResultBeforePolicy: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, + ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, }}, }, - installSetPolicies: func(t *testing.T, dut2 *ygnmi.Client) { + installPolicies: func(t *testing.T, dut1, dut2, dut3, dut4, dut5 *Device) { if debug { fmt.Println("Installing test policies") } @@ -64,6 +65,7 @@ func TestCommunitySet(t *testing.T) { // Create prefix set prefixSetName := "accept-" + prefix1 prefix1Path := ocpath.Root().RoutingPolicy().DefinedSets().PrefixSet(prefixSetName).Prefix(prefix1, "exact").IpPrefix() + Replace(t, dut1, prefix1Path.Config(), prefix1) Replace(t, dut2, prefix1Path.Config(), prefix1) policy := &oc.RoutingPolicy_PolicyDefinition_Statement_OrderedMap{} @@ -84,16 +86,13 @@ func TestCommunitySet(t *testing.T) { // Accept the route so that it may be advertised. stmt.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) // Install policy - Replace(t, dut2, ocpath.Root().RoutingPolicy().PolicyDefinition(policyName).Config(), &oc.RoutingPolicy_PolicyDefinition{Statement: policy}) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut1spec.RouterID).ApplyPolicy().ImportPolicy().Config(), []string{policyName}) - }, - installPolicies: func(t *testing.T, dut2 *ygnmi.Client) { - if debug { - fmt.Println("Installing test policies") - } + Replace(t, dut1, ocpath.Root().RoutingPolicy().PolicyDefinition(policyName).Config(), &oc.RoutingPolicy_PolicyDefinition{Statement: policy}) + Replace(t, dut1, bgp.BGPPath.Neighbor(dut2.RouterID).ApplyPolicy().ExportPolicy().Config(), []string{policyName}) + + ////////////////////// // Policy to reject routes with the given community set - policyName := "def2" + policyName = "def2" // Create community set rejectCommSetName := "reject-community-set" @@ -103,8 +102,8 @@ func TestCommunitySet(t *testing.T) { }) Replace(t, dut2, ocpath.Root().RoutingPolicy().DefinedSets().BgpDefinedSets().CommunitySet(rejectCommSetName).MatchSetOptions().Config(), oc.RoutingPolicy_MatchSetOptionsType_ANY) - policy := &oc.RoutingPolicy_PolicyDefinition_Statement_OrderedMap{} - stmt, err := policy.AppendNew("stmt2") + policy = &oc.RoutingPolicy_PolicyDefinition_Statement_OrderedMap{} + stmt, err = policy.AppendNew("stmt2") if err != nil { t.Fatalf("Cannot append new BGP policy statement: %v", err) } @@ -113,7 +112,7 @@ func TestCommunitySet(t *testing.T) { stmt.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_REJECT_ROUTE) // Install policy Replace(t, dut2, ocpath.Root().RoutingPolicy().PolicyDefinition(policyName).Config(), &oc.RoutingPolicy_PolicyDefinition{Statement: policy}) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut3spec.RouterID).ApplyPolicy().ExportPolicy().Config(), []string{policyName}) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut1.RouterID).ApplyPolicy().ImportPolicy().Config(), []string{policyName}) }, }) } diff --git a/bgp/tests/local_tests/policy_test.go b/bgp/tests/local_tests/policy_test.go index 080913e2..2e6180f3 100644 --- a/bgp/tests/local_tests/policy_test.go +++ b/bgp/tests/local_tests/policy_test.go @@ -31,18 +31,25 @@ import ( const ( debug = true - rejectTimeout = 10 * time.Second + rejectTimeout = 20 * time.Second ) // PolicyTestCase contains the specifications for a single policy test. // -// Limitations: -// * Does not check path attributes. -// * Only checks export policies. +// Topology: +// +// DUT1 (AS 64500) -> DUT2 (AS 64500) -> DUT3 (AS 64501) +// ^ +// | +// DUT4 (AS 64502) -> DUT5 (AS 64500) +// +// Currently by convention, all policies are installed on DUT1 (export), DUT5 +// (export), and DUT2 (import). This is because GoBGP only withdraws routes on +// import policy change after a soft reset: +// https://github.com/osrg/gobgp/blob/master/docs/sources/policy.md#policy-and-soft-reset type PolicyTestCase struct { - spec *valpb.PolicyTestCase - installSetPolicies func(t *testing.T, dut2 *ygnmi.Client) - installPolicies func(t *testing.T, dut2 *ygnmi.Client) + spec *valpb.PolicyTestCase + installPolicies func(t *testing.T, dut1, dut2, dut3, dut4, dut5 *Device) } // testPolicy is the helper policy integration tests can call to instantiate @@ -58,8 +65,70 @@ func testPolicy(t *testing.T, testspec PolicyTestCase) { }) } +func testPropagation(t *testing.T, routeTest *valpb.RouteTestCase, prevDUT, currDUT, nextDUT *Device, filterPoliciesInstalled bool) { + t.Helper() + v4uni := bgp.BGPPath.Rib().AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast() + expectedResult := routeTest.GetExpectedResultBeforePolicy() + if filterPoliciesInstalled { + expectedResult = routeTest.GetExpectedResult() + } + + prefix := routeTest.GetInput().GetReachPrefix() + // Check propagation to AdjRibOutPre for all prefixes. + Await(t, prevDUT, v4uni.Neighbor(currDUT.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, prevDUT, v4uni.Neighbor(currDUT.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) + Await(t, currDUT, v4uni.Neighbor(prevDUT.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) + switch expectedResult { + case policyval.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT: + t.Logf("Waiting for %s to be propagated", prefix) + Await(t, currDUT, v4uni.Neighbor(prevDUT.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), prefix) + Await(t, currDUT, v4uni.LocRib().Route(prefix, oc.UnionString(prevDUT.RouterID), 0).Prefix().State(), prefix) + Await(t, currDUT, v4uni.Neighbor(nextDUT.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, currDUT, v4uni.Neighbor(nextDUT.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) + Await(t, nextDUT, v4uni.Neighbor(currDUT.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) + case policyval.RouteTestResult_ROUTE_TEST_RESULT_DISCARD: + w := Watch(t, currDUT, v4uni.Neighbor(prevDUT.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), rejectTimeout, func(val *ygnmi.Value[string]) bool { + _, ok := val.Val() + return !ok + }) + if _, ok := w.Await(t); !ok { + t.Errorf("prefix %q (%s) was not rejected from adj-rib-in-post of %v (neighbour %v) within timeout.", prefix, routeTest.GetDescription(), currDUT, prevDUT.ID) + break + } + t.Logf("prefix %q (%s) was successfully rejected from adj-rib-in-post of %v (neighbour %v) within timeout.", prefix, routeTest.GetDescription(), currDUT, prevDUT.ID) + + // Test withdrawal in the case of InstallPolicyAfterRoutes. + w = Watch(t, nextDUT, v4uni.Neighbor(currDUT.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), rejectTimeout, func(val *ygnmi.Value[string]) bool { + _, ok := val.Val() + return !ok + }) + if _, ok := w.Await(t); !ok { + t.Errorf("prefix %q (%s) was not rejected from adj-rib-in-pre of %v (neighbour %v) within timeout.", prefix, routeTest.GetDescription(), nextDUT, currDUT.ID) + break + } + t.Logf("prefix %q (%s) was successfully rejected from adj-rib-in-pre of %v (neighbour %v) within timeout.", prefix, routeTest.GetDescription(), nextDUT, currDUT.ID) + case policyval.RouteTestResult_ROUTE_TEST_RESULT_NOT_PREFERRED: + Await(t, currDUT, v4uni.Neighbor(prevDUT.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), prefix) + w := Watch(t, currDUT, v4uni.LocRib().Route(prefix, oc.UnionString(prevDUT.RouterID), 0).Prefix().State(), rejectTimeout, func(val *ygnmi.Value[string]) bool { + _, ok := val.Val() + return !ok + }) + if _, ok := w.Await(t); !ok { + t.Errorf("prefix %q with origin %q (%s) was selected into loc-rib of %v.", prefix, prevDUT.ID, routeTest.GetDescription(), currDUT) + break + } + t.Logf("prefix %q with origin %q (%s) was successfully not selected into loc-rib of %v within timeout.", prefix, prevDUT.ID, routeTest.GetDescription(), currDUT) + + Await(t, currDUT, v4uni.Neighbor(nextDUT.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, currDUT, v4uni.Neighbor(nextDUT.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) + Await(t, nextDUT, v4uni.Neighbor(currDUT.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) + default: + t.Fatalf("Invalid or unhandled policy result: %v", expectedResult) + } +} + func testPolicyAux(t *testing.T, testspec PolicyTestCase, installPolicyAfterRoutes bool) { - dut1, stop1 := newLemming(t, dut1spec, []*AddIntfAction{{ + dut1, stop1 := newLemming(t, 1, 64500, []*AddIntfAction{{ name: "eth0", ifindex: 0, enabled: true, @@ -67,33 +136,53 @@ func testPolicyAux(t *testing.T, testspec PolicyTestCase, installPolicyAfterRout niName: "DEFAULT", }}) defer stop1() - dut2, stop2 := newLemming(t, dut2spec, nil) + dut2, stop2 := newLemming(t, 2, 64500, nil) defer stop2() - dut3, stop3 := newLemming(t, dut3spec, nil) + dut3, stop3 := newLemming(t, 3, 64501, nil) defer stop3() + dut4, stop4 := newLemming(t, 4, 64502, []*AddIntfAction{{ + name: "eth0", + ifindex: 0, + enabled: true, + prefix: "192.0.2.1/30", + niName: "DEFAULT", + }}) + defer stop4() + dut5, stop5 := newLemming(t, 5, 64500, []*AddIntfAction{{ + name: "eth0", + ifindex: 0, + enabled: true, + prefix: "193.0.2.1/30", + niName: "DEFAULT", + }}) + defer stop5() installDefaultPolicies := func() { // Clear the path for routes to be propagated. - Replace(t, dut1, bgp.BGPPath.Neighbor(dut2spec.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut1spec.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut3spec.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut3, bgp.BGPPath.Neighbor(dut2spec.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - } - installDefaultPolicies() + // DUT1 -> DUT2 -> DUT3 + Replace(t, dut1, bgp.BGPPath.Neighbor(dut2.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut1.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut3.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut3, bgp.BGPPath.Neighbor(dut2.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - if testspec.installSetPolicies != nil { - testspec.installSetPolicies(t, dut2) + // This is an alternate source of routes towards DUT2 and thereby DUT3. + // Note that this path is longer than the above path: + // DUT4 -> DUT5 -> DUT2 (-> DUT3) + Replace(t, dut4, bgp.BGPPath.Neighbor(dut5.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut5, bgp.BGPPath.Neighbor(dut4.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut5, bgp.BGPPath.Neighbor(dut2.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut5.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) } + installDefaultPolicies() if testspec.installPolicies != nil && !installPolicyAfterRoutes { - testspec.installPolicies(t, dut2) + testspec.installPolicies(t, dut1, dut2, dut3, dut4, dut5) } - establishSessionPair(t, dut1, dut2, dut1spec, dut2spec) - establishSessionPair(t, dut2, dut3, dut2spec, dut3spec) + establishSessionPairs(t, []DevicePair{{dut1, dut2}, {dut2, dut3}, {dut4, dut5}, {dut5, dut2}}...) for _, routeTest := range testspec.spec.RouteTests { - // Install all test routes into DUT1. + // Install all regular test routes into DUT1. route := &oc.NetworkInstance_Protocol_Static{ Prefix: ygot.String(routeTest.GetInput().GetReachPrefix()), NextHop: map[string]*oc.NetworkInstance_Protocol_Static_NextHop{ @@ -107,92 +196,68 @@ func testPolicyAux(t *testing.T, testspec PolicyTestCase, installPolicyAfterRout installStaticRoute(t, dut1, route) } + for _, routeTest := range testspec.spec.LongerPathRouteTests { + // Install all longer-path test routes into DUT4. + route := &oc.NetworkInstance_Protocol_Static{ + Prefix: ygot.String(routeTest.GetInput().GetReachPrefix()), + NextHop: map[string]*oc.NetworkInstance_Protocol_Static_NextHop{ + "single": { + Index: ygot.String("single"), + NextHop: oc.UnionString("192.0.2.1"), + Recurse: ygot.Bool(true), + }, + }, + } + installStaticRoute(t, dut4, route) + } + + for _, routeTest := range testspec.spec.AlternatePathRouteTests { + // Install all alternate-path test routes into DUT5. + route := &oc.NetworkInstance_Protocol_Static{ + Prefix: ygot.String(routeTest.GetInput().GetReachPrefix()), + NextHop: map[string]*oc.NetworkInstance_Protocol_Static_NextHop{ + "single": { + Index: ygot.String("single"), + NextHop: oc.UnionString("193.0.2.1"), + Recurse: ygot.Bool(true), + }, + }, + } + installStaticRoute(t, dut5, route) + } + staticp := ocpath.Root().NetworkInstance(fakedevice.DefaultNetworkInstance).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, fakedevice.StaticRoutingProtocol) v := GetAll(t, dut1, staticp.StaticAny().Config()) t.Logf("Installed static route on %v: %s", dut1, formatYgot(v)) - v4uni := bgp.BGPPath.Rib().AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast() - for _, routeTest := range testspec.spec.RouteTests { - prefix := routeTest.GetInput().GetReachPrefix() - // Check propagation to AdjRibOutPre for all prefixes. - Await(t, dut1, v4uni.Neighbor(dut2spec.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut1, v4uni.Neighbor(dut2spec.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut1spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut1spec.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.LocRib().Route(prefix, oc.UnionString(dut1spec.RouterID), 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) - if routeTest.GetExpectedResult() == policyval.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT || installPolicyAfterRoutes { - t.Logf("Waiting for %s to be propagated", prefix) - Await(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut3, v4uni.Neighbor(dut2spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) - } else { - w := Watch(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), rejectTimeout, func(val *ygnmi.Value[string]) bool { - _, ok := val.Val() - return ok - }) - if _, ok := w.Await(t); ok { - t.Errorf("prefix %q (%s) was not rejected.", prefix, routeTest.GetDescription()) - } - } + testPropagation(t, routeTest, dut1, dut2, dut3, !installPolicyAfterRoutes) + } + for _, routeTest := range testspec.spec.LongerPathRouteTests { + testPropagation(t, routeTest, dut5, dut2, dut3, !installPolicyAfterRoutes) } if installPolicyAfterRoutes { - awaitNewSession := make(chan error) - go func() { - if _, err := AwaitWithErr(dut2, bgp.BGPPath.Neighbor(dut3spec.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_IDLE); err != nil { - awaitNewSession <- err - } - if _, err := AwaitWithErr(dut3, bgp.BGPPath.Neighbor(dut2spec.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_IDLE); err != nil { - awaitNewSession <- err - } - if _, err := AwaitWithErr(dut2, bgp.BGPPath.Neighbor(dut3spec.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_ESTABLISHED); err != nil { - awaitNewSession <- err - } - if _, err := AwaitWithErr(dut3, bgp.BGPPath.Neighbor(dut2spec.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_ESTABLISHED); err != nil { - awaitNewSession <- err - } - awaitNewSession <- nil - }() - testspec.installPolicies(t, dut2) - // Changing policy resets the BGP session, which causes routes - // to disappear from the AdjRIBs, so we need to wait for - // re-establishment first. - if err := <-awaitNewSession; err != nil { - t.Fatal(err) + if testspec.installPolicies != nil { + testspec.installPolicies(t, dut1, dut2, dut3, dut4, dut5) } + // Changing policy currently causes a hard reset of the BGP + // session, which causes routes to disappear from the AdjRIBs, + // so we need to wait for re-establishment first. To do this, + // we sleep for a reasonable amount of time for the sessions to + // be teared down. + // + // TODO(wenbli): Check if we can make the config amenable to a + // soft reset. + time.Sleep(10 * time.Second) + awaitSessionEstablished(t, dut2, dut1) + awaitSessionEstablished(t, dut2, dut5) for _, routeTest := range testspec.spec.RouteTests { - prefix := routeTest.GetInput().GetReachPrefix() - - Await(t, dut2, v4uni.Neighbor(dut1spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut1spec.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.LocRib().Route(prefix, oc.UnionString(dut1spec.RouterID), 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) - if routeTest.GetExpectedResult() == policyval.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT { - Await(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut3, v4uni.Neighbor(dut2spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) - } else { - // Check rejected prefix has been withdrawn from AdjRib-out of DUT2 and AdjRib-in of DUT3. - w := Watch(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), rejectTimeout, func(val *ygnmi.Value[string]) bool { - _, ok := val.Val() - return !ok - }) - if _, ok := w.Await(t); !ok { - t.Errorf("prefix %q (%s) was not rejected within timeout.", prefix, routeTest.GetDescription()) - } else { - t.Logf("prefix %q (%s) was successfully rejected from DUT2's AdjRibOutPost within timeout.", prefix, routeTest.GetDescription()) - } - w = Watch(t, dut3, v4uni.Neighbor(dut2spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), rejectTimeout, func(val *ygnmi.Value[string]) bool { - _, ok := val.Val() - return !ok - }) - if _, ok := w.Await(t); !ok { - t.Errorf("prefix %q (%s) was not withdrawn from DUT3 within timeout.", prefix, routeTest.GetDescription()) - } else { - t.Logf("prefix %q (%s) was successfully not seen at DUT3's AdjRibInPre within timeout.", prefix, routeTest.GetDescription()) - } - } + testPropagation(t, routeTest, dut1, dut2, dut3, true) + } + for _, routeTest := range testspec.spec.LongerPathRouteTests { + testPropagation(t, routeTest, dut5, dut2, dut3, true) } } } diff --git a/bgp/tests/local_tests/prefix_set_test.go b/bgp/tests/local_tests/prefix_set_test.go index fe6d0e2f..7c924e8a 100644 --- a/bgp/tests/local_tests/prefix_set_test.go +++ b/bgp/tests/local_tests/prefix_set_test.go @@ -21,7 +21,6 @@ import ( "github.com/openconfig/lemming/bgp" "github.com/openconfig/lemming/gnmi/oc" "github.com/openconfig/lemming/gnmi/oc/ocpath" - "github.com/openconfig/ygnmi/ygnmi" valpb "github.com/openconfig/lemming/bgp/tests/proto/policyval" ) @@ -35,16 +34,18 @@ func TestPrefixSet(t *testing.T) { Input: &valpb.TestRoute{ ReachPrefix: "10.33.0.0/16", }, - ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_DISCARD, + ExpectedResultBeforePolicy: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, + ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_DISCARD, }, { Description: "Accepted route", Input: &valpb.TestRoute{ ReachPrefix: "10.3.0.0/16", }, - ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, + ExpectedResultBeforePolicy: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, + ExpectedResult: valpb.RouteTestResult_ROUTE_TEST_RESULT_ACCEPT, }}, }, - installPolicies: func(t *testing.T, dut2 *ygnmi.Client) { + installPolicies: func(t *testing.T, dut1, dut2, _, _, _ *Device) { if debug { fmt.Println("Installing test policies") } @@ -69,7 +70,7 @@ func TestPrefixSet(t *testing.T) { stmt.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_REJECT_ROUTE) // Install policy Replace(t, dut2, ocpath.Root().RoutingPolicy().PolicyDefinition(policyName).Config(), &oc.RoutingPolicy_PolicyDefinition{Statement: policy}) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut3spec.RouterID).ApplyPolicy().ExportPolicy().Config(), []string{policyName}) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut1.RouterID).ApplyPolicy().ImportPolicy().Config(), []string{policyName}) }, }) } diff --git a/bgp/tests/local_tests/route_propagation_test.go b/bgp/tests/local_tests/route_propagation_test.go index d1a5d12d..31cb52ee 100644 --- a/bgp/tests/local_tests/route_propagation_test.go +++ b/bgp/tests/local_tests/route_propagation_test.go @@ -22,11 +22,10 @@ import ( "github.com/openconfig/lemming/gnmi/fakedevice" "github.com/openconfig/lemming/gnmi/oc" "github.com/openconfig/lemming/gnmi/oc/ocpath" - "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" ) -func installStaticRoute(t *testing.T, dut *ygnmi.Client, route *oc.NetworkInstance_Protocol_Static) { +func installStaticRoute(t *testing.T, dut *Device, route *oc.NetworkInstance_Protocol_Static) { staticp := ocpath.Root().NetworkInstance(fakedevice.DefaultNetworkInstance). Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, fakedevice.StaticRoutingProtocol) Replace(t, dut, staticp.Static(*route.Prefix).Config(), route) @@ -42,7 +41,7 @@ func formatYgot(v any) string { } func TestRoutePropagation(t *testing.T) { - dut1, stop1 := newLemming(t, dut1spec, []*AddIntfAction{{ + dut1, stop1 := newLemming(t, 1, 64500, []*AddIntfAction{{ name: "eth0", ifindex: 0, enabled: true, @@ -56,11 +55,11 @@ func TestRoutePropagation(t *testing.T) { niName: "DEFAULT", }}) defer stop1() - dut2, stop2 := newLemming(t, dut2spec, nil) + dut2, stop2 := newLemming(t, 2, 64501, nil) defer stop2() - dut3, stop3 := newLemming(t, dut3spec, nil) + dut3, stop3 := newLemming(t, 3, 64502, nil) defer stop3() - dut4, stop4 := newLemming(t, dut4spec, nil) + dut4, stop4 := newLemming(t, 4, 64503, nil) defer stop4() installDefaultPolicies := func() { @@ -70,18 +69,16 @@ func TestRoutePropagation(t *testing.T) { // route_propagation_test.go:68: Replace(t) on ygnmi client (target: "dut1") at /network-instances/network-instance[name=DEFAULT]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor[neighbor-address=127.0.0.2]/apply-policy/config/default-export-policy: Replace(t) at path origin:"openconfig" elem:{name:"network-instances"} elem:{name:"network-instance" key:{key:"name" value:"DEFAULT"}} elem:{name:"protocols"} elem:{name:"protocol" key:{key:"identifier" value:"BGP"} key:{key:"name" value:"BGP"}} elem:{name:"bgp"} elem:{name:"neighbors"} elem:{name:"neighbor" key:{key:"neighbor-address" value:"127.0.0.2"}} elem:{name:"apply-policy"} elem:{name:"config"} elem:{name:"default-export-policy"}: rpc error: code = Internal desc = update is stale, update is stale, update is stale fmt.Println("Installing default policies") // Clear the path for routes to be propagated. - Replace(t, dut1, bgp.BGPPath.Neighbor(dut2spec.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut1spec.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut2, bgp.BGPPath.Neighbor(dut3spec.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut3, bgp.BGPPath.Neighbor(dut2spec.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut3, bgp.BGPPath.Neighbor(dut4spec.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) - Replace(t, dut4, bgp.BGPPath.Neighbor(dut3spec.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut1, bgp.BGPPath.Neighbor(dut2.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut1.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut2, bgp.BGPPath.Neighbor(dut3.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut3, bgp.BGPPath.Neighbor(dut2.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut3, bgp.BGPPath.Neighbor(dut4.RouterID).ApplyPolicy().DefaultExportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) + Replace(t, dut4, bgp.BGPPath.Neighbor(dut3.RouterID).ApplyPolicy().DefaultImportPolicy().Config(), oc.RoutingPolicy_DefaultPolicyType_ACCEPT_ROUTE) } installDefaultPolicies() - establishSessionPair(t, dut1, dut2, dut1spec, dut2spec) - establishSessionPair(t, dut2, dut3, dut2spec, dut3spec) - establishSessionPair(t, dut3, dut4, dut3spec, dut4spec) + establishSessionPairs(t, []DevicePair{{dut1, dut2}, {dut2, dut3}, {dut3, dut4}}...) prefix := "10.10.10.0/24" installStaticRoute(t, dut1, &oc.NetworkInstance_Protocol_Static{ @@ -101,17 +98,17 @@ func TestRoutePropagation(t *testing.T) { v4uni := ocpath.Root().NetworkInstance(fakedevice.DefaultNetworkInstance).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, fakedevice.BGPRoutingProtocol).Bgp().Rib().AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast() // Check route is in Adj-In of dut2. - Await(t, dut2, v4uni.Neighbor(dut1spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut1spec.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), prefix) + Await(t, dut2, v4uni.Neighbor(dut1.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, dut2, v4uni.Neighbor(dut1.RouterID).AdjRibInPost().Route(prefix, 0).Prefix().State(), prefix) // Check route is in Loc-RIB of dut2. - Await(t, dut2, v4uni.LocRib().Route(prefix, oc.UnionString(dut1spec.RouterID), 0).Prefix().State(), prefix) + Await(t, dut2, v4uni.LocRib().Route(prefix, oc.UnionString(dut1.RouterID), 0).Prefix().State(), prefix) // Check route is in Adj-Out of dut2. - Await(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) - Await(t, dut2, v4uni.Neighbor(dut3spec.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) + Await(t, dut2, v4uni.Neighbor(dut3.RouterID).AdjRibOutPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, dut2, v4uni.Neighbor(dut3.RouterID).AdjRibOutPost().Route(prefix, 0).Prefix().State(), prefix) // Check route is in Adj-In of dut3. - Await(t, dut3, v4uni.Neighbor(dut2spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, dut3, v4uni.Neighbor(dut2.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) // Check route is in Adj-In of dut4. - Await(t, dut4, v4uni.Neighbor(dut3spec.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) + Await(t, dut4, v4uni.Neighbor(dut3.RouterID).AdjRibInPre().Route(prefix, 0).Prefix().State(), prefix) } diff --git a/bgp/tests/local_tests/session_establish_test.go b/bgp/tests/local_tests/session_establish_test.go index 22792257..7ec8cdeb 100644 --- a/bgp/tests/local_tests/session_establish_test.go +++ b/bgp/tests/local_tests/session_establish_test.go @@ -19,7 +19,9 @@ package local_test import ( "context" "fmt" + "net" "net/netip" + "sync/atomic" "testing" "github.com/openconfig/lemming" @@ -39,53 +41,26 @@ import ( // TODO: Consolidate test helper code with integration and other unit tests. -type DeviceSpec struct { - ID uint - gnmiPort uint - gribiPort uint - bgpPort uint16 - AS uint32 - RouterID string +type Device struct { + yc *ygnmi.Client + ID uint + AS uint32 + bgpPort uint16 + RouterID string +} + +func nextLocalHostAddr() string { + // Start at 127.0.0.2 + return netip.AddrFrom4([4]byte{127, 0, 0, byte(nextLocalHostAddrIndex.Add(1) + 1)}).String() } var ( - dut1spec = DeviceSpec{ - ID: 1, - gnmiPort: 7339, - gribiPort: 7340, - bgpPort: 1111, - AS: 64500, - RouterID: "127.0.0.1", - } - dut2spec = DeviceSpec{ - ID: 2, - gnmiPort: 8339, - gribiPort: 8340, - bgpPort: 1112, - AS: 64501, - RouterID: "127.0.0.2", - } - dut3spec = DeviceSpec{ - ID: 3, - gnmiPort: 9339, - gribiPort: 9340, - bgpPort: 1113, - AS: 64502, - RouterID: "127.0.0.3", - } - dut4spec = DeviceSpec{ - ID: 4, - gnmiPort: 9439, - gribiPort: 9440, - bgpPort: 1114, - AS: 64503, - RouterID: "127.0.0.4", - } + nextLocalHostAddrIndex = &atomic.Uint32{} ) -func ygnmiClient(t *testing.T, target string, port int) *ygnmi.Client { +func ygnmiClient(t *testing.T, target, dialTarget string) *ygnmi.Client { t.Helper() - conn, err := grpc.Dial(fmt.Sprintf("localhost:%d", port), grpc.WithTransportCredentials(local.NewCredentials())) + conn, err := grpc.Dial(dialTarget, grpc.WithTransportCredentials(local.NewCredentials())) if err != nil { t.Fatalf("cannot dial gNMI server, %v", err) } @@ -150,12 +125,15 @@ func bgpWithNbr(as uint32, routerID string, nbr *oc.NetworkInstance_Protocol_Bgp return bgp } -func newLemming(t *testing.T, dev DeviceSpec, connectedIntfs []*AddIntfAction) (*ygnmi.Client, func()) { - opts := []lemming.Option{lemming.WithTransportCreds(insecure.NewCredentials()), lemming.WithGRIBIAddr(fmt.Sprintf(":%d", dev.gribiPort)), lemming.WithGNMIAddr(fmt.Sprintf(":%d", dev.gnmiPort)), lemming.WithBGPPort(dev.bgpPort)} +func newLemming(t *testing.T, id uint, as uint32, connectedIntfs []*AddIntfAction) (*Device, func()) { + routerID := nextLocalHostAddr() + gnmiTarget := net.JoinHostPort(routerID, "7339") + gribiTarget := net.JoinHostPort(routerID, "7340") + opts := []lemming.Option{lemming.WithTransportCreds(insecure.NewCredentials()), lemming.WithGRIBIAddr(gribiTarget), lemming.WithGNMIAddr(gnmiTarget), lemming.WithBGPPort(1111)} - target := fmt.Sprintf("dut%d", dev.ID) + target := fmt.Sprintf("dut%d", id) - l, err := lemming.New(target, fmt.Sprintf("unix:/tmp/zserv-test%d.api", dev.ID), opts...) + l, err := lemming.New(target, fmt.Sprintf("unix:/tmp/zserv-test%d.api", id), opts...) if err != nil { t.Fatal(err) } @@ -164,47 +142,61 @@ func newLemming(t *testing.T, dev DeviceSpec, connectedIntfs []*AddIntfAction) ( configureInterface(t, intf, l.GNMI()) } - return ygnmiClient(t, target, int(dev.gnmiPort)), func() { l.Stop() } + return &Device{ + yc: ygnmiClient(t, target, gnmiTarget), + ID: id, + AS: as, + bgpPort: 1111, + RouterID: routerID, + }, func() { l.Stop() } +} + +type DevicePair struct { + first *Device + second *Device } -func establishSessionPair(t *testing.T, dut1, dut2 *ygnmi.Client, spec1, spec2 DeviceSpec) { +func establishSessionPairs(t *testing.T, dutPairs ...DevicePair) { t.Helper() - dutConf := bgpWithNbr(spec1.AS, spec1.RouterID, &oc.NetworkInstance_Protocol_Bgp_Neighbor{ - PeerAs: ygot.Uint32(spec2.AS), - NeighborAddress: ygot.String(spec2.RouterID), - NeighborPort: ygot.Uint16(spec2.bgpPort), - }) - dut2Conf := bgpWithNbr(spec2.AS, spec2.RouterID, &oc.NetworkInstance_Protocol_Bgp_Neighbor{ - PeerAs: ygot.Uint32(spec1.AS), - NeighborAddress: ygot.String(spec1.RouterID), - NeighborPort: ygot.Uint16(spec1.bgpPort), - }) - Update(t, dut1, bgp.BGPPath.Config(), dutConf) - Update(t, dut2, bgp.BGPPath.Config(), dut2Conf) - - awaitSessionEstablished(t, dut1, dut2, spec1, spec2) + for _, pair := range dutPairs { + dut1, dut2 := pair.first, pair.second + dutConf := bgpWithNbr(dut1.AS, dut1.RouterID, &oc.NetworkInstance_Protocol_Bgp_Neighbor{ + PeerAs: ygot.Uint32(dut2.AS), + NeighborAddress: ygot.String(dut2.RouterID), + NeighborPort: ygot.Uint16(dut2.bgpPort), + Transport: &oc.NetworkInstance_Protocol_Bgp_Neighbor_Transport{ + LocalAddress: ygot.String(dut1.RouterID), + }, + }) + dut2Conf := bgpWithNbr(dut2.AS, dut2.RouterID, &oc.NetworkInstance_Protocol_Bgp_Neighbor{ + PeerAs: ygot.Uint32(dut1.AS), + NeighborAddress: ygot.String(dut1.RouterID), + NeighborPort: ygot.Uint16(dut1.bgpPort), + Transport: &oc.NetworkInstance_Protocol_Bgp_Neighbor_Transport{ + LocalAddress: ygot.String(dut2.RouterID), + }, + }) + Update(t, dut1, bgp.BGPPath.Config(), dutConf) + Update(t, dut2, bgp.BGPPath.Config(), dut2Conf) + } + + for _, pair := range dutPairs { + dut1, dut2 := pair.first, pair.second + awaitSessionEstablished(t, dut1, dut2) + } } -func awaitSessionEstablished(t *testing.T, dut1, dut2 *ygnmi.Client, spec1, spec2 DeviceSpec) { +func awaitSessionEstablished(t *testing.T, dut1, dut2 *Device) { t.Helper() - Await(t, dut1, bgp.BGPPath.Neighbor(spec2.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_ESTABLISHED) - Await(t, dut2, bgp.BGPPath.Neighbor(spec1.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_ESTABLISHED) + Await(t, dut1, bgp.BGPPath.Neighbor(dut2.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_ESTABLISHED) + Await(t, dut2, bgp.BGPPath.Neighbor(dut1.RouterID).SessionState().State(), oc.Bgp_Neighbor_SessionState_ESTABLISHED) } func TestSessionEstablish(t *testing.T) { - dut1, stop1 := newLemming(t, dut1spec, nil) + dut1, stop1 := newLemming(t, 1, 64500, nil) defer stop1() - dut2, stop2 := newLemming(t, dut2spec, nil) - defer stop2() - - establishSessionPair(t, dut1, dut2, dut1spec, dut2spec) -} - -func TestEstablishDifferentIP(t *testing.T) { - dut2, stop2 := newLemming(t, dut2spec, nil) + dut2, stop2 := newLemming(t, 2, 64501, nil) defer stop2() - dut3, stop3 := newLemming(t, dut3spec, nil) - defer stop3() - establishSessionPair(t, dut2, dut3, dut2spec, dut3spec) + establishSessionPairs(t, DevicePair{first: dut1, second: dut2}) } diff --git a/bgp/tests/local_tests/ygnmi_test.go b/bgp/tests/local_tests/ygnmi_test.go index ec861740..a94e67f4 100644 --- a/bgp/tests/local_tests/ygnmi_test.go +++ b/bgp/tests/local_tests/ygnmi_test.go @@ -29,14 +29,15 @@ import ( ) const ( - awaitTimeLimit = 20 * time.Second + awaitTimeLimit = 30 * time.Second ) // Get fetches the value of a SingletonQuery with a ONCE subscription, // failing the test fatally if no value is present at the path. // Use Lookup to also get metadata or tolerate no value present. -func Get[T any](t testing.TB, c *ygnmi.Client, q ygnmi.SingletonQuery[T]) T { +func Get[T any](t testing.TB, dut *Device, q ygnmi.SingletonQuery[T]) T { t.Helper() + c := dut.yc v, err := ygnmi.Get(context.Background(), c, q) if err != nil { t.Fatalf("Get(t) on %s at %v: %v", c, q, err) @@ -49,16 +50,17 @@ func Get[T any](t testing.TB, c *ygnmi.Client, q ygnmi.SingletonQuery[T]) T { // Use Lookup to also get metadata or tolerate no value present. // Note: This is a workaround for Go's type inference not working for this use case and may be removed in a subsequent release. // Note: This is equivalent to calling Get with a ConfigQuery and providing a fully-qualified type parameter. -func GetConfig[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T]) T { +func GetConfig[T any](t testing.TB, dut *Device, q ygnmi.ConfigQuery[T]) T { t.Helper() - return Get[T](t, c, q) + return Get[T](t, dut, q) } // GetAll fetches the value of a WildcardQuery with a ONCE subscription skipping any non-present paths. // It fails the test fatally if no value is present at the path // Use LookupAll to also get metadata or tolerate no values present. -func GetAll[T any](t testing.TB, c *ygnmi.Client, q ygnmi.WildcardQuery[T]) []T { +func GetAll[T any](t testing.TB, dut *Device, q ygnmi.WildcardQuery[T]) []T { t.Helper() + c := dut.yc v, err := ygnmi.GetAll(context.Background(), c, q) if err != nil { t.Fatalf("GetAll(t) on %s at %v: %v", c, q, err) @@ -67,8 +69,9 @@ func GetAll[T any](t testing.TB, c *ygnmi.Client, q ygnmi.WildcardQuery[T]) []T } // Update updates the configuration at the given query path with the val. -func Update[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T], val T) *ygnmi.Result { +func Update[T any](t testing.TB, dut *Device, q ygnmi.ConfigQuery[T], val T) *ygnmi.Result { t.Helper() + c := dut.yc res, err := ygnmi.Update(context.Background(), c, q, val) if err != nil { t.Fatalf("Update(t) on %v at %v: %v", c, q, err) @@ -77,8 +80,9 @@ func Update[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T], val T) } // Replace replaces the configuration at the given query path with the val. -func Replace[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T], val T) *ygnmi.Result { +func Replace[T any](t testing.TB, dut *Device, q ygnmi.ConfigQuery[T], val T) *ygnmi.Result { t.Helper() + c := dut.yc res, err := ygnmi.Replace(context.Background(), c, q, val) if err != nil { t.Fatalf("Replace(t) on %v at %v: %v", c, q, err) @@ -87,8 +91,9 @@ func Replace[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T], val T } // Delete deletes the configuration at the given query path. -func Delete[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T]) *ygnmi.Result { +func Delete[T any](t testing.TB, dut *Device, q ygnmi.ConfigQuery[T]) *ygnmi.Result { t.Helper() + c := dut.yc res, err := ygnmi.Delete(context.Background(), c, q) if err != nil { t.Fatalf("Delete(t) on %v at %v: %v", c, q, err) @@ -100,8 +105,9 @@ func Delete[T any](t testing.TB, c *ygnmi.Client, q ygnmi.ConfigQuery[T]) *ygnmi // blocking until a value that is deep equal to the specified val is received // or the timeout is reached. To wait for a generic predicate, or to make a // non-blocking call, use the Watch method instead. -func Await[T any](t testing.TB, c *ygnmi.Client, q ygnmi.SingletonQuery[T], val T) *ygnmi.Value[T] { +func Await[T any](t testing.TB, dut *Device, q ygnmi.SingletonQuery[T], val T) *ygnmi.Value[T] { t.Helper() + c := dut.yc ctx, cancel := context.WithTimeout(context.Background(), awaitTimeLimit) defer cancel() v, err := ygnmi.Await(ctx, c, q, val) @@ -114,9 +120,10 @@ func Await[T any](t testing.TB, c *ygnmi.Client, q ygnmi.SingletonQuery[T], val // AwaitWithErr is the same as Await except an error is returned. // // Its purpose is to add a better error message. -func AwaitWithErr[T any](c *ygnmi.Client, q ygnmi.SingletonQuery[T], val T) (*ygnmi.Value[T], error) { +func AwaitWithErr[T any](dut *Device, q ygnmi.SingletonQuery[T], val T) (*ygnmi.Value[T], error) { ctx, cancel := context.WithTimeout(context.Background(), awaitTimeLimit) defer cancel() + c := dut.yc v, err := ygnmi.Await(ctx, c, q, val) if err != nil { return v, fmt.Errorf("Await(t) on %v at %v: %v", c, q, err) @@ -173,8 +180,9 @@ func (w *Watcher[T]) Cancel() { // or the timeout is reached. Calling Await on the returned Watcher waits for the subscription // to complete. It returns the last observed value and a boolean that indicates whether // that value satisfies the predicate. -func Watch[T any](t testing.TB, c *ygnmi.Client, q ygnmi.SingletonQuery[T], timeout time.Duration, pred func(*ygnmi.Value[T]) bool) *Watcher[T] { +func Watch[T any](t testing.TB, dut *Device, q ygnmi.SingletonQuery[T], timeout time.Duration, pred func(*ygnmi.Value[T]) bool) *Watcher[T] { t.Helper() + c := dut.yc ctx, cancel := context.WithTimeout(context.Background(), timeout) w := ygnmi.Watch(ctx, c, q, func(v *ygnmi.Value[T]) error { if ok := pred(v); ok { diff --git a/bgp/tests/proto/policyval/policy_validation.pb.go b/bgp/tests/proto/policyval/policy_validation.pb.go index 26ad11b9..5cfe277a 100644 --- a/bgp/tests/proto/policyval/policy_validation.pb.go +++ b/bgp/tests/proto/policyval/policy_validation.pb.go @@ -23,9 +23,10 @@ const ( type RouteTestResult int32 const ( - RouteTestResult_ROUTE_TEST_RESULT_UNSPECIFIED RouteTestResult = 0 - RouteTestResult_ROUTE_TEST_RESULT_ACCEPT RouteTestResult = 1 - RouteTestResult_ROUTE_TEST_RESULT_DISCARD RouteTestResult = 2 + RouteTestResult_ROUTE_TEST_RESULT_UNSPECIFIED RouteTestResult = 0 + RouteTestResult_ROUTE_TEST_RESULT_ACCEPT RouteTestResult = 1 + RouteTestResult_ROUTE_TEST_RESULT_DISCARD RouteTestResult = 2 + RouteTestResult_ROUTE_TEST_RESULT_NOT_PREFERRED RouteTestResult = 3 ) // Enum value maps for RouteTestResult. @@ -34,11 +35,13 @@ var ( 0: "ROUTE_TEST_RESULT_UNSPECIFIED", 1: "ROUTE_TEST_RESULT_ACCEPT", 2: "ROUTE_TEST_RESULT_DISCARD", + 3: "ROUTE_TEST_RESULT_NOT_PREFERRED", } RouteTestResult_value = map[string]int32{ - "ROUTE_TEST_RESULT_UNSPECIFIED": 0, - "ROUTE_TEST_RESULT_ACCEPT": 1, - "ROUTE_TEST_RESULT_DISCARD": 2, + "ROUTE_TEST_RESULT_UNSPECIFIED": 0, + "ROUTE_TEST_RESULT_ACCEPT": 1, + "ROUTE_TEST_RESULT_DISCARD": 2, + "ROUTE_TEST_RESULT_NOT_PREFERRED": 3, } ) @@ -74,8 +77,10 @@ type PolicyTestCase struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` - RouteTests []*RouteTestCase `protobuf:"bytes,4,rep,name=route_tests,json=routeTests,proto3" json:"route_tests,omitempty"` + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + RouteTests []*RouteTestCase `protobuf:"bytes,4,rep,name=route_tests,json=routeTests,proto3" json:"route_tests,omitempty"` + AlternatePathRouteTests []*RouteTestCase `protobuf:"bytes,5,rep,name=alternate_path_route_tests,json=alternatePathRouteTests,proto3" json:"alternate_path_route_tests,omitempty"` + LongerPathRouteTests []*RouteTestCase `protobuf:"bytes,6,rep,name=longer_path_route_tests,json=longerPathRouteTests,proto3" json:"longer_path_route_tests,omitempty"` } func (x *PolicyTestCase) Reset() { @@ -124,6 +129,20 @@ func (x *PolicyTestCase) GetRouteTests() []*RouteTestCase { return nil } +func (x *PolicyTestCase) GetAlternatePathRouteTests() []*RouteTestCase { + if x != nil { + return x.AlternatePathRouteTests + } + return nil +} + +func (x *PolicyTestCase) GetLongerPathRouteTests() []*RouteTestCase { + if x != nil { + return x.LongerPathRouteTests + } + return nil +} + type TestRoute struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -176,9 +195,10 @@ type RouteTestCase struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` - Input *TestRoute `protobuf:"bytes,2,opt,name=input,proto3" json:"input,omitempty"` - ExpectedResult RouteTestResult `protobuf:"varint,3,opt,name=expected_result,json=expectedResult,proto3,enum=policy_validation.RouteTestResult" json:"expected_result,omitempty"` + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + Input *TestRoute `protobuf:"bytes,2,opt,name=input,proto3" json:"input,omitempty"` + ExpectedResultBeforePolicy RouteTestResult `protobuf:"varint,3,opt,name=expected_result_before_policy,json=expectedResultBeforePolicy,proto3,enum=policy_validation.RouteTestResult" json:"expected_result_before_policy,omitempty"` + ExpectedResult RouteTestResult `protobuf:"varint,4,opt,name=expected_result,json=expectedResult,proto3,enum=policy_validation.RouteTestResult" json:"expected_result,omitempty"` } func (x *RouteTestCase) Reset() { @@ -227,6 +247,13 @@ func (x *RouteTestCase) GetInput() *TestRoute { return nil } +func (x *RouteTestCase) GetExpectedResultBeforePolicy() RouteTestResult { + if x != nil { + return x.ExpectedResultBeforePolicy + } + return RouteTestResult_ROUTE_TEST_RESULT_UNSPECIFIED +} + func (x *RouteTestCase) GetExpectedResult() RouteTestResult { if x != nil { return x.ExpectedResult @@ -241,40 +268,60 @@ var file_bgp_tests_proto_policyval_policy_validation_proto_rawDesc = []byte{ 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x76, 0x61, 0x6c, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x75, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xad, 0x02, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, + 0x73, 0x65, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x5d, + 0x0a, 0x1a, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, + 0x43, 0x61, 0x73, 0x65, 0x52, 0x17, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x57, 0x0a, + 0x17, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, + 0x52, 0x14, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x54, 0x65, 0x73, 0x74, 0x73, 0x22, 0x2e, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x68, 0x5f, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x61, 0x63, 0x68, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x99, 0x02, 0x0a, 0x0d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, - 0x65, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x73, 0x22, 0x2e, 0x0a, - 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, - 0x61, 0x63, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x72, 0x65, 0x61, 0x63, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0xb2, 0x01, - 0x0a, 0x0d, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x05, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x4b, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, + 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x65, + 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x65, + 0x0a, 0x1d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, + 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x1a, 0x65, 0x78, 0x70, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x4b, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x2a, 0x71, 0x0a, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, - 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x54, - 0x45, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x41, 0x43, - 0x43, 0x45, 0x50, 0x54, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, - 0x54, 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x44, 0x49, 0x53, 0x43, - 0x41, 0x52, 0x44, 0x10, 0x02, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6c, - 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x62, 0x67, 0x70, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x76, 0x61, 0x6c, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x74, 0x2a, 0x96, 0x01, 0x0a, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, + 0x54, 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, + 0x54, 0x45, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x41, + 0x43, 0x43, 0x45, 0x50, 0x54, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x4f, 0x55, 0x54, 0x45, + 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x44, 0x49, 0x53, + 0x43, 0x41, 0x52, 0x44, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, + 0x54, 0x45, 0x53, 0x54, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, + 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x52, 0x45, 0x44, 0x10, 0x03, 0x42, 0x39, 0x5a, 0x37, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6c, 0x65, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x2f, 0x62, 0x67, 0x70, + 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x76, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -299,13 +346,16 @@ var file_bgp_tests_proto_policyval_policy_validation_proto_goTypes = []interface } var file_bgp_tests_proto_policyval_policy_validation_proto_depIdxs = []int32{ 3, // 0: policy_validation.PolicyTestCase.route_tests:type_name -> policy_validation.RouteTestCase - 2, // 1: policy_validation.RouteTestCase.input:type_name -> policy_validation.TestRoute - 0, // 2: policy_validation.RouteTestCase.expected_result:type_name -> policy_validation.RouteTestResult - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 3, // 1: policy_validation.PolicyTestCase.alternate_path_route_tests:type_name -> policy_validation.RouteTestCase + 3, // 2: policy_validation.PolicyTestCase.longer_path_route_tests:type_name -> policy_validation.RouteTestCase + 2, // 3: policy_validation.RouteTestCase.input:type_name -> policy_validation.TestRoute + 0, // 4: policy_validation.RouteTestCase.expected_result_before_policy:type_name -> policy_validation.RouteTestResult + 0, // 5: policy_validation.RouteTestCase.expected_result:type_name -> policy_validation.RouteTestResult + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_bgp_tests_proto_policyval_policy_validation_proto_init() } diff --git a/bgp/tests/proto/policyval/policy_validation.proto b/bgp/tests/proto/policyval/policy_validation.proto index 399044f8..b5ea4d90 100644 --- a/bgp/tests/proto/policyval/policy_validation.proto +++ b/bgp/tests/proto/policyval/policy_validation.proto @@ -22,6 +22,8 @@ option go_package = "github.com/openconfig/lemming/bgp/tests/proto/policyval"; message PolicyTestCase { string description = 1; repeated RouteTestCase route_tests = 4; + repeated RouteTestCase alternate_path_route_tests = 5; + repeated RouteTestCase longer_path_route_tests = 6; } // This message represents a single prefix and its associated BGP attributes. @@ -36,6 +38,8 @@ enum RouteTestResult { ROUTE_TEST_RESULT_ACCEPT = 1; // Discard the input TestRoute. ROUTE_TEST_RESULT_DISCARD = 2; + // Input TestRoute not selected by best path selection. + ROUTE_TEST_RESULT_NOT_PREFERRED = 3; } // Specifies an input route and expected output. @@ -47,5 +51,6 @@ enum RouteTestResult { message RouteTestCase { string description = 1; TestRoute input = 2; - RouteTestResult expected_result = 3; + RouteTestResult expected_result_before_policy = 3; + RouteTestResult expected_result = 4; } diff --git a/repositories.bzl b/repositories.bzl index b2d6bd1c..64deb6c7 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -48,8 +48,8 @@ def go_repositories(): go_repository( name = "com_github_alecthomas_units", importpath = "github.com/alecthomas/units", - sum = "h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=", - version = "v0.0.0-20190717042225-c3de453c63f4", + sum = "h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=", + version = "v0.0.0-20211218093645-b94a6e3cc137", ) go_repository( name = "com_github_andybalholm_brotli", @@ -1157,8 +1157,8 @@ def go_repositories(): go_repository( name = "com_github_julienschmidt_httprouter", importpath = "github.com/julienschmidt/httprouter", - sum = "h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=", - version = "v1.2.0", + sum = "h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=", + version = "v1.3.0", ) go_repository( name = "com_github_jung_kurt_gofpdf", @@ -1226,8 +1226,8 @@ def go_repositories(): go_repository( name = "com_github_konsorten_go_windows_terminal_sequences", importpath = "github.com/konsorten/go-windows-terminal-sequences", - sum = "h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=", - version = "v1.0.1", + sum = "h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=", + version = "v1.0.3", ) go_repository( @@ -1420,8 +1420,8 @@ def go_repositories(): go_repository( name = "com_github_mwitkow_go_conntrack", importpath = "github.com/mwitkow/go-conntrack", - sum = "h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc=", - version = "v0.0.0-20161129095857-cc309e4a2223", + sum = "h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=", + version = "v0.0.0-20190716064945-2f068394615f", ) go_repository( @@ -1572,8 +1572,8 @@ def go_repositories(): "gazelle:resolve go github.com/p4lang/p4runtime/go/p4/v1 @com_github_p4lang_p4runtime//:p4runtime_go_proto", ], importpath = "github.com/openconfig/ondatra", - sum = "h1:hR1OQ5oW5BFz4BX5HU7jhh45Wy9eIAQULnljowfNDhU=", - version = "v0.2.5", + sum = "h1:abEI0qO4Q/BrXV/qi2unXn8dpkZFp9DF8rw6kZod5/E=", + version = "v0.2.7", ) go_repository( name = "com_github_openconfig_testt", @@ -2393,8 +2393,8 @@ def go_repositories(): go_repository( name = "com_google_cloud_go_gaming", importpath = "cloud.google.com/go/gaming", - sum = "h1:5qZmZEWzMf8GEFgm9NeC3bjFRpt7x4S6U7oLbxaf7N8=", - version = "v1.10.1", + sum = "h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc=", + version = "v1.9.0", ) go_repository( name = "com_google_cloud_go_gkebackup", @@ -2423,8 +2423,8 @@ def go_repositories(): go_repository( name = "com_google_cloud_go_grafeas", importpath = "cloud.google.com/go/grafeas", - sum = "h1:oyTL/KjiUeBs9eYLw/40cpSZglUC+0F7X4iu/8t7NWs=", - version = "v0.3.0", + sum = "h1:CYjC+xzdPvbV65gi6Dr4YowKcmLo045pm18L0DhdELM=", + version = "v0.2.0", ) go_repository( name = "com_google_cloud_go_gsuiteaddons", @@ -3321,8 +3321,8 @@ def go_repositories(): go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", - sum = "h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=", - version = "v0.9.1", + sum = "h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=", + version = "v0.7.0", ) go_repository( name = "org_golang_x_xerrors",