Created
June 18, 2018 20:49
-
-
Save cstockton/db3cc222471e4e9858d3b60290e3b7f8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package deletetest | |
| import ( | |
| "context" | |
| "encoding/json" | |
| "io" | |
| "testing" | |
| "time" | |
| gobgpapi "github.com/osrg/gobgp/api" | |
| "github.com/osrg/gobgp/packet/bgp" | |
| "github.com/osrg/gobgp/table" | |
| // "github.secureserver.net/infosec-network/go-protect/pkg/internal/worker" | |
| "google.golang.org/grpc" | |
| "google.golang.org/grpc/codes" | |
| ) | |
| func newPath(length uint8, pfx, nh string) *table.Path { | |
| addr := bgp.NewIPAddrPrefix(length, pfx) | |
| attrs := []bgp.PathAttributeInterface{ | |
| bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP), | |
| bgp.NewPathAttributeNextHop(nh), | |
| bgp.NewPathAttributeCommunities([]uint32{105546}), | |
| } | |
| return table.NewPath(nil, addr, false, attrs, time.Now().In(time.UTC), false) | |
| } | |
| func helpClient(ctx context.Context, tb testing.TB) gobgpapi.GobgpApiClient { | |
| conn, err := grpc.DialContext(ctx, "localhost:51053", | |
| grpc.WithInsecure(), | |
| grpc.WithTimeout(time.Second*30), | |
| ) | |
| if err != nil { | |
| tb.Fatal(err) | |
| } | |
| return gobgpapi.NewGobgpApiClient(conn) | |
| } | |
| func helpDump(tb testing.TB, label string, v interface{}) { | |
| d, err := json.MarshalIndent(v, "", " ") | |
| if err != nil { | |
| tb.Logf("%v: (err %v):\n%v\n", label, err, d) | |
| return | |
| } | |
| tb.Logf("%v:\n%v\n", label, string(d)) | |
| } | |
| // Tested against 1.32 | |
| // ================================================ | |
| func TestDelete(t *testing.T) { | |
| ctx, cancel := context.WithTimeout(context.Background(), time.Minute) | |
| defer cancel() | |
| cli := helpClient(ctx, t) | |
| pool := New(4) | |
| worker := pool.Worker(cli) | |
| // go worker.Work(ctx) // for InjectMrt streaming. | |
| go worker(ctx) // for InjectMrt streaming. | |
| get := func(tb testing.TB, pfx string) *table.Path { | |
| stream, err := cli.GetPath(ctx, &gobgpapi.GetPathRequest{ | |
| Type: gobgpapi.Resource_GLOBAL, | |
| Family: uint32(bgp.RF_IPv4_UC), | |
| Prefixes: []*gobgpapi.TableLookupPrefix{ | |
| { | |
| Prefix: pfx, | |
| LookupOption: gobgpapi.TableLookupOption_LOOKUP_EXACT, | |
| }, | |
| }, | |
| }) | |
| if err != nil { | |
| tb.Fatal(err) | |
| } | |
| defer closeStream(stream) | |
| p, err := stream.Recv() | |
| if err != nil { | |
| if err == io.EOF { | |
| return nil | |
| } | |
| tb.Fatal(err) | |
| } | |
| path, err := p.ToNativePath() | |
| if err != nil { | |
| tb.Fatal(err) | |
| } | |
| return path | |
| } | |
| add := func(tb testing.TB, length uint8, pfx, nh string) *table.Path { | |
| p := newPath(length, pfx, nh) | |
| _, err := cli.AddPath(ctx, &gobgpapi.AddPathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(p, nil), | |
| }) | |
| if err != nil { | |
| tb.Fatalf("exp nil err from AddPath; got %v", err) | |
| } | |
| return p | |
| } | |
| addMrt := func(tb testing.TB, length uint8, pfx, nh string) *table.Path { | |
| p := newPath(length, pfx, nh) | |
| if err := pool.Send(ctx, p); err != nil { | |
| tb.Fatalf("exp nil err from AddPath; got %v", err) | |
| } | |
| search := p.GetNlri().String() | |
| for i := 0; i < 20; i++ { | |
| time.Sleep(time.Second / 10) | |
| if get(tb, search) != nil { | |
| return p | |
| } | |
| } | |
| return p | |
| } | |
| t.Run("Length32", func(t *testing.T) { | |
| t.Run("AddPath/Delete/ByGetPath", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.1", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByGetPath", func(t *testing.T) { | |
| added := addMrt(t, 32, "10.0.0.2", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByClonedGetPath", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.3", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got.Clone(true), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByClonedGetPath", func(t *testing.T) { | |
| added := addMrt(t, 32, "10.0.0.4", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got.Clone(true), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByNewPath", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.5", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(newPath(32, "10.0.0.5", "192.168.0.1"), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByNewPath", func(t *testing.T) { | |
| added := addMrt(t, 32, "10.0.0.6", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(newPath(32, "10.0.0.6", "192.168.0.1"), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByOfficialClientMethod", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.7", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| nlri := got.GetNlri() | |
| n, err := nlri.Serialize() | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: &gobgpapi.Path{ | |
| Nlri: n, | |
| Family: uint32(got.GetRouteFamily()), | |
| Identifier: nlri.PathIdentifier(), | |
| LocalIdentifier: nlri.PathLocalIdentifier(), | |
| }, | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByOfficialClientMethod", func(t *testing.T) { | |
| added := addMrt(t, 32, "10.0.0.8", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| nlri := got.GetNlri() | |
| n, err := nlri.Serialize() | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: &gobgpapi.Path{ | |
| Nlri: n, | |
| Family: uint32(got.GetRouteFamily()), | |
| Identifier: nlri.PathIdentifier(), | |
| LocalIdentifier: nlri.PathLocalIdentifier(), | |
| }, | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByGetPathSetWithdraw", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.9", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| req.Path.IsWithdraw = true | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByGetPath/ClearNils", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.10", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| req.Path.SourceId = "" | |
| req.Path.NeighborIp = "" | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByGetPath/ClearAsn", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.11", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| // req.Path.LocalIdentifier = 0 | |
| req.Path.SourceAsn = 0 | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| }) | |
| t.Run("Length24", func(t *testing.T) { | |
| t.Run("AddPath/Delete/ByGetPath", func(t *testing.T) { | |
| added := add(t, 24, "10.0.1.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByGetPath", func(t *testing.T) { | |
| added := addMrt(t, 24, "10.0.2.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got, nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByClonedGetPath", func(t *testing.T) { | |
| added := add(t, 24, "10.0.3.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got.Clone(true), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByClonedGetPath", func(t *testing.T) { | |
| added := addMrt(t, 24, "10.0.4.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(got.Clone(true), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByNewPath", func(t *testing.T) { | |
| added := add(t, 24, "10.0.5.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(newPath(24, "10.0.5.0", "192.168.0.1"), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByNewPath", func(t *testing.T) { | |
| added := addMrt(t, 24, "10.0.6.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: gobgpapi.ToPathApi(newPath(24, "10.0.6.0", "192.168.0.1"), nil), | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("AddPath/Delete/ByOfficialClientMethod", func(t *testing.T) { | |
| added := add(t, 24, "10.0.7.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| nlri := got.GetNlri() | |
| n, err := nlri.Serialize() | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: &gobgpapi.Path{ | |
| Nlri: n, | |
| Family: uint32(got.GetRouteFamily()), | |
| Identifier: nlri.PathIdentifier(), | |
| LocalIdentifier: nlri.PathLocalIdentifier(), | |
| }, | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| t.Run("InjectMrt/Delete/ByOfficialClientMethod", func(t *testing.T) { | |
| added := addMrt(t, 24, "10.0.8.0", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| nlri := got.GetNlri() | |
| n, err := nlri.Serialize() | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| req := gobgpapi.DeletePathRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Path: &gobgpapi.Path{ | |
| Nlri: n, | |
| Family: uint32(got.GetRouteFamily()), | |
| Identifier: nlri.PathIdentifier(), | |
| LocalIdentifier: nlri.PathLocalIdentifier(), | |
| }, | |
| } | |
| helpDump(t, "*api.Path:", req.Path) | |
| if _, err := cli.DeletePath(ctx, &req); err != nil { | |
| t.Fatal(err) | |
| } | |
| verify := get(t, added.GetNlri().String()) | |
| if verify != nil { | |
| t.Errorf("verify failed, found path: %v", verify) | |
| } | |
| }) | |
| }) | |
| t.Run("Compare/ClonedVsNew", func(t *testing.T) { | |
| added := add(t, 32, "10.0.0.9", "192.168.0.1") | |
| got := get(t, added.GetNlri().String()) | |
| if got == nil { | |
| t.Fatal("path was not added") | |
| } | |
| helpDump(t, `GetPath`, gobgpapi.ToPathApi(got, nil)) | |
| cloned := gobgpapi.ToPathApi(got.Clone(true), nil) | |
| helpDump(t, `GetPath.Clone`, cloned) | |
| create := gobgpapi.ToPathApi(newPath(32, "10.0.0.9", "192.168.0.1"), nil) | |
| helpDump(t, `table.NewPath`, create) | |
| t.Fail() | |
| }) | |
| } | |
| // still not even sure if this is how you properly close streams, see: | |
| // | |
| // https://github.com/grpc/grpc-go/issues/2015 | |
| // | |
| func closeStream(stream grpc.ClientStream) (err error) { | |
| stream.CloseSend() | |
| switch T := stream.(type) { | |
| case gobgpapi.GobgpApi_GetPathClient: | |
| for err == nil { | |
| _, err = T.Recv() | |
| } | |
| } | |
| return | |
| } | |
| type request struct { | |
| ctx context.Context | |
| req gobgpapi.InjectMrtRequest | |
| errCh chan error | |
| } | |
| func newRequest() *request { | |
| return &request{ | |
| req: gobgpapi.InjectMrtRequest{ | |
| Resource: gobgpapi.Resource_GLOBAL, | |
| Paths: make([]*gobgpapi.Path, 0, 16), | |
| }, | |
| errCh: make(chan error), | |
| } | |
| } | |
| // Pool provides a pool of GoBGP path injectmrt workers. | |
| type Pool struct { | |
| poolCh chan *request | |
| workCh chan *request | |
| } | |
| // New returns a new *Pool of the given size, which represents the number of request | |
| // slots available in the pool. | |
| func New(size int) *Pool { | |
| if size <= 0 { | |
| panic("injectmrt: size must be >= 1") | |
| } | |
| p := &Pool{ | |
| workCh: make(chan *request), | |
| poolCh: make(chan *request, size), | |
| } | |
| for i := 0; i < size; i++ { | |
| p.poolCh <- newRequest() | |
| } | |
| return p | |
| } | |
| // acquire attempts to acquire a request from the pool. | |
| func (p *Pool) acquire(ctx context.Context) (*request, error) { | |
| select { | |
| case r := <-p.poolCh: | |
| r.ctx = ctx | |
| r.req.Paths = r.req.Paths[0:0] | |
| return r, nil | |
| case <-ctx.Done(): | |
| return nil, ctx.Err() | |
| } | |
| } | |
| // release attempts to release the request back to the pool. | |
| func (p *Pool) release(r *request) { | |
| select { | |
| case p.poolCh <- r: | |
| default: | |
| panic("injectmrt: release beyond bounds") | |
| } | |
| } | |
| // Send attempts to send a path via the gobgp inject mrt api. | |
| func (p *Pool) Send(ctx context.Context, ps ...*table.Path) error { | |
| r, err := p.acquire(ctx) | |
| if err != nil { | |
| return err | |
| } | |
| defer p.release(r) | |
| // add paths | |
| for _, p := range ps { | |
| r.req.Paths = append(r.req.Paths, gobgpapi.ToPathApi(p, nil)) | |
| } | |
| select { | |
| case p.workCh <- r: | |
| select { | |
| case err := <-r.errCh: | |
| return err | |
| case <-ctx.Done(): | |
| return ctx.Err() | |
| } | |
| case <-ctx.Done(): | |
| return ctx.Err() | |
| } | |
| } | |
| // Worker returns an implementation of worker.Work that will use the given | |
| // client to process Pool requests. | |
| // func (p *Pool) Worker(cli gobgpapi.GobgpApiClient) worker.Worker { | |
| func (p *Pool) Worker(cli gobgpapi.GobgpApiClient) func(ctx context.Context) error { | |
| return func(ctx context.Context) error { | |
| sr, err := cli.InjectMrt(ctx) | |
| if err != nil { | |
| return err | |
| } | |
| defer func() { | |
| sr.CloseAndRecv() | |
| sr.CloseSend() | |
| }() | |
| for { | |
| select { | |
| case r := <-p.workCh: | |
| err := sr.Send(&r.req) | |
| // Can't select ctx.Done() here, but also don't need to. A recv guarantees | |
| // that r.ctx is done, or a receiver is ready. | |
| select { | |
| case r.errCh <- err: | |
| case <-r.ctx.Done(): // Request ctx is done, will never be received. | |
| } | |
| // Handle potential failure scenarios. | |
| switch { | |
| case err == nil: | |
| continue | |
| case err == io.EOF: | |
| return nil | |
| case grpc.Code(err) == codes.Canceled: | |
| return context.Canceled | |
| default: | |
| return err // Let exponential backoff trigger | |
| } | |
| case <-ctx.Done(): | |
| return ctx.Err() | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| === RUN TestDelete | |
| === RUN TestDelete/Length32 | |
| === RUN TestDelete/Length32/AddPath/Delete/ByGetPath | |
| === RUN TestDelete/Length32/InjectMrt/Delete/ByGetPath | |
| === RUN TestDelete/Length32/AddPath/Delete/ByClonedGetPath | |
| === RUN TestDelete/Length32/InjectMrt/Delete/ByClonedGetPath | |
| === RUN TestDelete/Length32/AddPath/Delete/ByNewPath | |
| === RUN TestDelete/Length32/InjectMrt/Delete/ByNewPath | |
| === RUN TestDelete/Length32/AddPath/Delete/ByOfficialClientMethod | |
| === RUN TestDelete/Length32/InjectMrt/Delete/ByOfficialClientMethod | |
| === RUN TestDelete/Length32/AddPath/Delete/ByGetPathSetWithdraw | |
| === RUN TestDelete/Length32/AddPath/Delete/ByGetPath/ClearNils | |
| === RUN TestDelete/Length32/AddPath/Delete/ByGetPath/ClearAsnAndIdent | |
| === RUN TestDelete/Length24 | |
| === RUN TestDelete/Length24/AddPath/Delete/ByGetPath | |
| === RUN TestDelete/Length24/InjectMrt/Delete/ByGetPath | |
| === RUN TestDelete/Length24/AddPath/Delete/ByClonedGetPath | |
| === RUN TestDelete/Length24/InjectMrt/Delete/ByClonedGetPath | |
| === RUN TestDelete/Length24/AddPath/Delete/ByNewPath | |
| === RUN TestDelete/Length24/InjectMrt/Delete/ByNewPath | |
| === RUN TestDelete/Length24/AddPath/Delete/ByOfficialClientMethod | |
| === RUN TestDelete/Length24/InjectMrt/Delete/ByOfficialClientMethod | |
| === RUN TestDelete/Compare/ClonedVsNew | |
| --- FAIL: TestDelete (0.86s) | |
| --- FAIL: TestDelete/Length32 (0.44s) | |
| --- FAIL: TestDelete/Length32/AddPath/Delete/ByGetPath (0.01s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAE=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:139: verify failed, found path: { 10.0.0.1/32 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length32/InjectMrt/Delete/ByGetPath (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAI=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:162: verify failed, found path: { 10.0.0.2/32 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length32/AddPath/Delete/ByClonedGetPath (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAM=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "is_withdraw": true, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:185: verify failed, found path: { 10.0.0.3/32 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length32/InjectMrt/Delete/ByClonedGetPath (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAQ=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "is_withdraw": true, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:208: verify failed, found path: { 10.0.0.4/32 | src: local, nh: 192.168.0.1 } | |
| --- PASS: TestDelete/Length32/AddPath/Delete/ByNewPath (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAU=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "QAMEwKgAAQ==", | |
| "wAgEAAGcSg==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537 | |
| } | |
| --- PASS: TestDelete/Length32/InjectMrt/Delete/ByNewPath (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAY=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "QAMEwKgAAQ==", | |
| "wAgEAAGcSg==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537 | |
| } | |
| --- PASS: TestDelete/Length32/AddPath/Delete/ByOfficialClientMethod (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAc=", | |
| "family": 65537, | |
| "local_identifier": 1 | |
| } | |
| --- PASS: TestDelete/Length32/InjectMrt/Delete/ByOfficialClientMethod (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAg=", | |
| "family": 65537, | |
| "local_identifier": 1 | |
| } | |
| --- FAIL: TestDelete/Length32/AddPath/Delete/ByGetPathSetWithdraw (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAk=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "is_withdraw": true, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:346: verify failed, found path: { 10.0.0.9/32 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length32/AddPath/Delete/ByGetPath/ClearNils (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAo=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:371: verify failed, found path: { 10.0.0.10/32 | src: local, nh: 192.168.0.1 } | |
| --- PASS: TestDelete/Length32/AddPath/Delete/ByGetPath/ClearAsnAndIdent (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "IAoAAAs=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| --- FAIL: TestDelete/Length24 (0.42s) | |
| --- FAIL: TestDelete/Length24/AddPath/Delete/ByGetPath (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoAAQ==", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:421: verify failed, found path: { 10.0.1.0/24 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length24/InjectMrt/Delete/ByGetPath (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoAAg==", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354908, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:444: verify failed, found path: { 10.0.2.0/24 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length24/AddPath/Delete/ByClonedGetPath (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoAAw==", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354909, | |
| "is_withdraw": true, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:467: verify failed, found path: { 10.0.3.0/24 | src: local, nh: 192.168.0.1 } | |
| --- FAIL: TestDelete/Length24/InjectMrt/Delete/ByClonedGetPath (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoABA==", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354909, | |
| "is_withdraw": true, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:490: verify failed, found path: { 10.0.4.0/24 | src: local, nh: 192.168.0.1 } | |
| --- PASS: TestDelete/Length24/AddPath/Delete/ByNewPath (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoABQ==", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "QAMEwKgAAQ==", | |
| "wAgEAAGcSg==" | |
| ], | |
| "age": 1529354909, | |
| "validation_detail": {}, | |
| "family": 65537 | |
| } | |
| --- PASS: TestDelete/Length24/InjectMrt/Delete/ByNewPath (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoABg==", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "QAMEwKgAAQ==", | |
| "wAgEAAGcSg==" | |
| ], | |
| "age": 1529354909, | |
| "validation_detail": {}, | |
| "family": 65537 | |
| } | |
| --- PASS: TestDelete/Length24/AddPath/Delete/ByOfficialClientMethod (0.00s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoABw==", | |
| "family": 65537, | |
| "local_identifier": 1 | |
| } | |
| --- PASS: TestDelete/Length24/InjectMrt/Delete/ByOfficialClientMethod (0.10s) | |
| deletetest_test.go:45: *api.Path:: | |
| { | |
| "nlri": "GAoACA==", | |
| "family": 65537, | |
| "local_identifier": 1 | |
| } | |
| --- FAIL: TestDelete/Compare/ClonedVsNew (0.00s) | |
| deletetest_test.go:45: GetPath: | |
| { | |
| "nlri": "IAoAAAk=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354909, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:45: GetPath.Clone: | |
| { | |
| "nlri": "IAoAAAk=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "wAgEAAGcSg==", | |
| "QAMEwKgAAQ==" | |
| ], | |
| "age": 1529354909, | |
| "is_withdraw": true, | |
| "validation_detail": {}, | |
| "family": 65537, | |
| "source_asn": 26496, | |
| "source_id": "\u003cnil\u003e", | |
| "neighbor_ip": "\u003cnil\u003e", | |
| "local_identifier": 1 | |
| } | |
| deletetest_test.go:45: table.NewPath: | |
| { | |
| "nlri": "IAoAAAk=", | |
| "pattrs": [ | |
| "QAEBAA==", | |
| "QAMEwKgAAQ==", | |
| "wAgEAAGcSg==" | |
| ], | |
| "age": 1529354909, | |
| "validation_detail": {}, | |
| "family": 65537 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment