diff options
Diffstat (limited to 'pkg/server')
-rw-r--r-- | pkg/server/bmp.go | 2 | ||||
-rw-r--r-- | pkg/server/grpc_server.go | 710 | ||||
-rw-r--r-- | pkg/server/server.go | 870 | ||||
-rw-r--r-- | pkg/server/server_test.go | 220 | ||||
-rw-r--r-- | pkg/server/zclient.go | 8 |
5 files changed, 946 insertions, 864 deletions
diff --git a/pkg/server/bmp.go b/pkg/server/bmp.go index 7904fae1..32daa677 100644 --- a/pkg/server/bmp.go +++ b/pkg/server/bmp.go @@ -225,7 +225,7 @@ func (b *bmpClient) loop() { } } case <-tickerCh: - neighborList := b.s.GetNeighbor("", true) + neighborList := b.s.getNeighbor("", true) for _, n := range neighborList { if n.State.SessionState != config.SESSION_STATE_ESTABLISHED { continue diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go index abce6ab4..c325ed41 100644 --- a/pkg/server/grpc_server.go +++ b/pkg/server/grpc_server.go @@ -38,7 +38,6 @@ import ( "github.com/osrg/gobgp/internal/pkg/apiutil" "github.com/osrg/gobgp/internal/pkg/config" "github.com/osrg/gobgp/internal/pkg/table" - "github.com/osrg/gobgp/internal/pkg/zebra" "github.com/osrg/gobgp/pkg/packet/bgp" ) @@ -436,17 +435,14 @@ func NewPeerGroupFromConfigStruct(pconf *config.PeerGroup) *api.PeerGroup { } } -func (s *Server) ListPeer(arg *api.ListPeerRequest, stream api.GobgpApi_ListPeerServer) error { - if arg == nil { - return fmt.Errorf("invalid request") - } - neighbors := s.bgpServer.GetNeighbor(arg.Address, arg.EnableAdvertised) - for _, e := range neighbors { - if err := stream.Send(&api.ListPeerResponse{Peer: NewPeerFromConfigStruct(e)}); err != nil { +func (s *Server) ListPeer(r *api.ListPeerRequest, stream api.GobgpApi_ListPeerServer) error { + l, err := s.bgpServer.ListPeer(context.Background(), r) + for _, e := range l { + if err := stream.Send(&api.ListPeerResponse{Peer: e}); err != nil { return err } } - return nil + return err } func NewValidationFromTableStruct(v *table.Validation) *api.RPKIValidation { @@ -511,64 +507,14 @@ func getValidation(v []*table.Validation, i int) *table.Validation { } } -func (s *Server) ListPath(arg *api.ListPathRequest, stream api.GobgpApi_ListPathServer) error { - f := func() []*table.LookupPrefix { - l := make([]*table.LookupPrefix, 0, len(arg.Prefixes)) - for _, p := range arg.Prefixes { - l = append(l, &table.LookupPrefix{ - Prefix: p.Prefix, - LookupOption: table.LookupOption(p.LookupOption), - }) +func (s *Server) ListPath(r *api.ListPathRequest, stream api.GobgpApi_ListPathServer) error { + dsts, err := s.bgpServer.ListPath(context.Background(), r) + for _, d := range dsts { + if err := stream.Send(&api.ListPathResponse{Destination: d}); err != nil { + return err } - return l - } - - in := false - family := bgp.RouteFamily(arg.Family) - var tbl *table.Table - var err error - var v []*table.Validation - switch arg.Type { - case api.Resource_LOCAL, api.Resource_GLOBAL: - tbl, v, err = s.bgpServer.GetRib(arg.Name, family, f()) - case api.Resource_ADJ_IN: - in = true - fallthrough - case api.Resource_ADJ_OUT: - tbl, v, err = s.bgpServer.GetAdjRib(arg.Name, family, in, f()) - case api.Resource_VRF: - tbl, err = s.bgpServer.GetVrfRib(arg.Name, family, []*table.LookupPrefix{}) - default: - return fmt.Errorf("unsupported resource type: %v", arg.Type) - } - if err != nil { - return err } - - idx := 0 - return func() error { - for _, dst := range tbl.GetDestinations() { - d := api.Destination{ - Prefix: dst.GetNlri().String(), - Paths: make([]*api.Path, 0, len(dst.GetAllKnownPathList())), - } - for i, path := range dst.GetAllKnownPathList() { - p := ToPathApi(path, getValidation(v, idx)) - idx++ - if i == 0 && !table.SelectionOptions.DisableBestPathSelection { - switch arg.Type { - case api.Resource_LOCAL, api.Resource_GLOBAL: - p.Best = true - } - } - d.Paths = append(d.Paths, p) - } - if err := stream.Send(&api.ListPathResponse{Destination: &d}); err != nil { - return err - } - } - return nil - }() + return err } func (s *Server) MonitorTable(arg *api.MonitorTableRequest, stream api.GobgpApi_MonitorTableServer) error { @@ -677,45 +623,24 @@ func (s *Server) MonitorPeer(arg *api.MonitorPeerRequest, stream api.GobgpApi_Mo }() } -func (s *Server) ResetPeer(ctx context.Context, arg *api.ResetPeerRequest) (*empty.Empty, error) { - if arg.Soft { - var err error - addr := arg.Address - if addr == "all" { - addr = "" - } - family := bgp.RouteFamily(0) - switch arg.Direction { - case api.ResetPeerRequest_IN: - err = s.bgpServer.SoftResetIn(addr, family) - case api.ResetPeerRequest_OUT: - err = s.bgpServer.SoftResetOut(addr, family) - default: - err = fmt.Errorf("unknown direction") - } - return &empty.Empty{}, err - } - return &empty.Empty{}, s.bgpServer.ResetNeighbor(arg.Address, arg.Communication) +func (s *Server) ResetPeer(ctx context.Context, r *api.ResetPeerRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ResetPeer(ctx, r) } -func (s *Server) ShutdownPeer(ctx context.Context, arg *api.ShutdownPeerRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.ShutdownNeighbor(arg.Address, arg.Communication) +func (s *Server) ShutdownPeer(ctx context.Context, r *api.ShutdownPeerRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ShutdownPeer(ctx, r) } -func (s *Server) EnablePeer(ctx context.Context, arg *api.EnablePeerRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.EnableNeighbor(arg.Address) +func (s *Server) EnablePeer(ctx context.Context, r *api.EnablePeerRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.EnableNeighbor(ctx, r) } -func (s *Server) DisablePeer(ctx context.Context, arg *api.DisablePeerRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DisableNeighbor(arg.Address, arg.Communication) +func (s *Server) DisablePeer(ctx context.Context, r *api.DisablePeerRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DisableNeighbor(ctx, r) } -func (s *Server) UpdatePolicy(ctx context.Context, arg *api.UpdatePolicyRequest) (*empty.Empty, error) { - rp, err := NewRoutingPolicyFromApiStruct(arg) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.UpdatePolicy(*rp) +func (s *Server) UpdatePolicy(ctx context.Context, r *api.UpdatePolicyRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.UpdatePolicy(ctx, r) } func NewAPIRoutingPolicyFromConfigStruct(c *config.RoutingPolicy) (*api.RoutingPolicy, error) { @@ -755,7 +680,7 @@ func NewRoutingPolicyFromApiStruct(arg *api.UpdatePolicyRequest) (*config.Routin }, nil } -func (s *Server) api2PathList(resource api.Resource, ApiPathList []*api.Path) ([]*table.Path, error) { +func api2PathList(resource api.Resource, ApiPathList []*api.Path) ([]*table.Path, error) { var pi *table.PeerInfo pathList := make([]*table.Path, 0, len(ApiPathList)) @@ -832,45 +757,25 @@ func (s *Server) api2PathList(resource api.Resource, ApiPathList []*api.Path) ([ return pathList, nil } -func (s *Server) AddPath(ctx context.Context, arg *api.AddPathRequest) (*api.AddPathResponse, error) { - pathList, err := s.api2PathList(arg.Resource, []*api.Path{arg.Path}) - var uuid []byte - if err == nil { - uuid, err = s.bgpServer.AddPath(arg.VrfId, pathList) - } - return &api.AddPathResponse{Uuid: uuid}, err +func (s *Server) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.AddPathResponse, error) { + return s.bgpServer.AddPath(ctx, r) } -func (s *Server) DeletePath(ctx context.Context, arg *api.DeletePathRequest) (*empty.Empty, error) { - pathList, err := func() ([]*table.Path, error) { - if arg.Path != nil { - arg.Path.IsWithdraw = true - return s.api2PathList(arg.Resource, []*api.Path{arg.Path}) - } - return []*table.Path{}, nil - }() - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.DeletePath(arg.Uuid, bgp.RouteFamily(arg.Family), arg.VrfId, pathList) +func (s *Server) DeletePath(ctx context.Context, r *api.DeletePathRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeletePath(ctx, r) } -func (s *Server) EnableMrt(ctx context.Context, arg *api.EnableMrtRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.EnableMrt(&config.MrtConfig{ - RotationInterval: arg.Interval, - DumpType: config.IntToMrtTypeMap[int(arg.DumpType)], - FileName: arg.Filename, - }) +func (s *Server) EnableMrt(ctx context.Context, r *api.EnableMrtRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.EnableMrt(ctx, r) } -func (s *Server) DisableMrt(ctx context.Context, arg *api.DisableMrtRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DisableMrt(&config.MrtConfig{}) +func (s *Server) DisableMrt(ctx context.Context, r *api.DisableMrtRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DisableMrt(ctx, r) } func (s *Server) AddPathStream(stream api.GobgpApi_AddPathStreamServer) error { for { arg, err := stream.Recv() - if err == io.EOF { break } else if err != nil { @@ -880,111 +785,52 @@ func (s *Server) AddPathStream(stream api.GobgpApi_AddPathStreamServer) error { if arg.Resource != api.Resource_GLOBAL && arg.Resource != api.Resource_VRF { return fmt.Errorf("unsupported resource: %s", arg.Resource) } - - if pathList, err := s.api2PathList(arg.Resource, arg.Paths); err != nil { + pathList, err := api2PathList(arg.Resource, arg.Paths) + if err != nil { + return err + } + err = s.bgpServer.addPathList(arg.VrfId, pathList) + if err != nil { return err - } else { - if _, err = s.bgpServer.AddPath("", pathList); err != nil { - return err - } } } return stream.SendAndClose(&empty.Empty{}) } -func (s *Server) AddBmp(ctx context.Context, arg *api.AddBmpRequest) (*empty.Empty, error) { - t, ok := config.IntToBmpRouteMonitoringPolicyTypeMap[int(arg.Type)] - if !ok { - return nil, fmt.Errorf("invalid bmp route monitoring policy: %d", arg.Type) - } - return &empty.Empty{}, s.bgpServer.AddBmp(&config.BmpServerConfig{ - Address: arg.Address, - Port: arg.Port, - RouteMonitoringPolicy: t, - }) +func (s *Server) AddBmp(ctx context.Context, r *api.AddBmpRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddBmp(ctx, r) } -func (s *Server) DeleteBmp(ctx context.Context, arg *api.DeleteBmpRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DeleteBmp(&config.BmpServerConfig{ - Address: arg.Address, - Port: arg.Port, - }) +func (s *Server) DeleteBmp(ctx context.Context, r *api.DeleteBmpRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeleteBmp(ctx, r) } -func (s *Server) AddRpki(ctx context.Context, arg *api.AddRpkiRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.AddRpki(&config.RpkiServerConfig{ - Address: arg.Address, - Port: arg.Port, - RecordLifetime: arg.Lifetime, - }) +func (s *Server) AddRpki(ctx context.Context, r *api.AddRpkiRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddRpki(ctx, r) } -func (s *Server) DeleteRpki(ctx context.Context, arg *api.DeleteRpkiRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DeleteRpki(&config.RpkiServerConfig{ - Address: arg.Address, - Port: arg.Port, - }) +func (s *Server) DeleteRpki(ctx context.Context, r *api.DeleteRpkiRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeleteRpki(ctx, r) } -func (s *Server) EnableRpki(ctx context.Context, arg *api.EnableRpkiRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.EnableRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) +func (s *Server) EnableRpki(ctx context.Context, r *api.EnableRpkiRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.EnableRpki(ctx, r) } -func (s *Server) DisableRpki(ctx context.Context, arg *api.DisableRpkiRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DisableRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) +func (s *Server) DisableRpki(ctx context.Context, r *api.DisableRpkiRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DisableRpki(ctx, r) } -func (s *Server) ResetRpki(ctx context.Context, arg *api.ResetRpkiRequest) (*empty.Empty, error) { - var err error - if arg.Soft { - err = s.bgpServer.SoftResetRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) - } else { - err = s.bgpServer.ResetRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) - } - return &empty.Empty{}, err +func (s *Server) ResetRpki(ctx context.Context, r *api.ResetRpkiRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ResetRpki(ctx, r) } -func (s *Server) ListRpki(arg *api.ListRpkiRequest, stream api.GobgpApi_ListRpkiServer) error { - servers, err := s.bgpServer.GetRpki() +func (s *Server) ListRpki(r *api.ListRpkiRequest, stream api.GobgpApi_ListRpkiServer) error { + servers, err := s.bgpServer.ListRpki(context.Background(), r) if err != nil { return err } - for _, s := range servers { - received := &s.State.RpkiMessages.RpkiReceived - sent := &s.State.RpkiMessages.RpkiSent - rpki := &api.Rpki{ - Conf: &api.RPKIConf{ - Address: s.Config.Address, - RemotePort: uint32(s.Config.Port), - }, - State: &api.RPKIState{ - Uptime: s.State.Uptime, - Downtime: s.State.Downtime, - Up: s.State.Up, - RecordIpv4: s.State.RecordsV4, - RecordIpv6: s.State.RecordsV6, - PrefixIpv4: s.State.PrefixesV4, - PrefixIpv6: s.State.PrefixesV6, - Serial: s.State.SerialNumber, - ReceivedIpv4: received.Ipv4Prefix, - ReceivedIpv6: received.Ipv6Prefix, - SerialNotify: received.SerialNotify, - CacheReset: received.CacheReset, - CacheResponse: received.CacheResponse, - EndOfData: received.EndOfData, - Error: received.Error, - SerialQuery: sent.SerialQuery, - ResetQuery: sent.ResetQuery, - }, - } + for _, rpki := range servers { if err := stream.Send(&api.ListRpkiResponse{Server: rpki}); err != nil { return err } @@ -992,12 +838,12 @@ func (s *Server) ListRpki(arg *api.ListRpkiRequest, stream api.GobgpApi_ListRpki return nil } -func (s *Server) ListRpkiTable(arg *api.ListRpkiTableRequest, stream api.GobgpApi_ListRpkiTableServer) error { - roas, err := s.bgpServer.GetRoa(bgp.RouteFamily(arg.Family)) +func (s *Server) ListRpkiTable(r *api.ListRpkiTableRequest, stream api.GobgpApi_ListRpkiTableServer) error { + roas, err := s.bgpServer.ListRpkiTable(context.Background(), r) if err != nil { return err } - for _, roa := range NewRoaListFromTableStructList(roas) { + for _, roa := range roas { if err := stream.Send(&api.ListRpkiTableResponse{Roa: roa}); err != nil { return err } @@ -1005,64 +851,25 @@ func (s *Server) ListRpkiTable(arg *api.ListRpkiTableRequest, stream api.GobgpAp return nil } -func (s *Server) EnableZebra(ctx context.Context, arg *api.EnableZebraRequest) (*empty.Empty, error) { - for _, p := range arg.RouteTypes { - if _, err := zebra.RouteTypeFromString(p); err != nil { - return &empty.Empty{}, err - } - } - return &empty.Empty{}, s.bgpServer.StartZebraClient(&config.ZebraConfig{ - Url: arg.Url, - RedistributeRouteTypeList: arg.RouteTypes, - Version: uint8(arg.Version), - NexthopTriggerEnable: arg.NexthopTriggerEnable, - NexthopTriggerDelay: uint8(arg.NexthopTriggerDelay), - }) +func (s *Server) EnableZebra(ctx context.Context, r *api.EnableZebraRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.EnableZebra(ctx, r) } -func (s *Server) ListVrf(arg *api.ListVrfRequest, stream api.GobgpApi_ListVrfServer) error { - toApi := func(v *table.Vrf) *api.Vrf { - return &api.Vrf{ - Name: v.Name, - Rd: apiutil.MarshalRD(v.Rd), - Id: v.Id, - ImportRt: apiutil.MarshalRTs(v.ImportRt), - ExportRt: apiutil.MarshalRTs(v.ExportRt), - } - } - vrfs := s.bgpServer.GetVrf() - for _, v := range vrfs { - if err := stream.Send(&api.ListVrfResponse{Vrf: toApi(v)}); err != nil { +func (s *Server) ListVrf(r *api.ListVrfRequest, stream api.GobgpApi_ListVrfServer) error { + for _, v := range s.bgpServer.ListVrf(context.Background(), r) { + if err := stream.Send(&api.ListVrfResponse{Vrf: v}); err != nil { return err } } return nil } -func (s *Server) AddVrf(ctx context.Context, arg *api.AddVrfRequest) (*empty.Empty, error) { - if arg == nil || arg.Vrf == nil { - return nil, fmt.Errorf("invalid request") - } - rd, err := apiutil.UnmarshalRD(arg.Vrf.Rd) - if err != nil { - return nil, err - } - im, err := apiutil.UnmarshalRTs(arg.Vrf.ImportRt) - if err != nil { - return nil, err - } - ex, err := apiutil.UnmarshalRTs(arg.Vrf.ExportRt) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.AddVrf(arg.Vrf.Name, arg.Vrf.Id, rd, im, ex) +func (s *Server) AddVrf(ctx context.Context, r *api.AddVrfRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddVrf(ctx, r) } -func (s *Server) DeleteVrf(ctx context.Context, arg *api.DeleteVrfRequest) (*empty.Empty, error) { - if arg == nil || arg.Name == "" { - return nil, fmt.Errorf("invalid request") - } - return &empty.Empty{}, s.bgpServer.DeleteVrf(arg.Name) +func (s *Server) DeleteVrf(ctx context.Context, r *api.DeleteVrfRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeleteVrf(ctx, r) } func ReadMpGracefulRestartFromAPIStruct(c *config.MpGracefulRestart, a *api.MpGracefulRestart) { @@ -1456,70 +1263,52 @@ func NewPeerGroupFromAPIStruct(a *api.PeerGroup) (*config.PeerGroup, error) { return pconf, nil } -func (s *Server) AddPeer(ctx context.Context, arg *api.AddPeerRequest) (*empty.Empty, error) { - c, err := NewNeighborFromAPIStruct(arg.Peer) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.AddNeighbor(c) +func (s *Server) AddPeer(ctx context.Context, r *api.AddPeerRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddPeer(ctx, r) } -func (s *Server) DeletePeer(ctx context.Context, arg *api.DeletePeerRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DeleteNeighbor(&config.Neighbor{Config: config.NeighborConfig{ - NeighborAddress: arg.Address, - NeighborInterface: arg.Interface, - }}) +func (s *Server) DeletePeer(ctx context.Context, r *api.DeletePeerRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeletePeer(ctx, r) } -func (s *Server) UpdatePeer(ctx context.Context, arg *api.UpdatePeerRequest) (*api.UpdatePeerResponse, error) { - c, err := NewNeighborFromAPIStruct(arg.Peer) - if err != nil { - return nil, err - } - needsSoftResetIn, err := s.bgpServer.UpdateNeighbor(c) +func (s *Server) UpdatePeer(ctx context.Context, r *api.UpdatePeerRequest) (*api.UpdatePeerResponse, error) { + rsp, err := s.bgpServer.UpdateNeighbor(ctx, r) if err != nil { return nil, err } - if arg.DoSoftResetIn && needsSoftResetIn { - return &api.UpdatePeerResponse{NeedsSoftResetIn: false}, s.bgpServer.SoftResetIn("", bgp.RouteFamily(0)) + if r.DoSoftResetIn && rsp.NeedsSoftResetIn { + return &api.UpdatePeerResponse{NeedsSoftResetIn: false}, s.bgpServer.ResetPeer(ctx, &api.ResetPeerRequest{ + Soft: true, + Direction: api.ResetPeerRequest_IN, + }) } - return &api.UpdatePeerResponse{NeedsSoftResetIn: needsSoftResetIn}, nil + return rsp, nil } -func (s *Server) AddPeerGroup(ctx context.Context, arg *api.AddPeerGroupRequest) (*empty.Empty, error) { - c, err := NewPeerGroupFromAPIStruct(arg.PeerGroup) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.AddPeerGroup(c) +func (s *Server) AddPeerGroup(ctx context.Context, r *api.AddPeerGroupRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddPeerGroup(ctx, r) } -func (s *Server) DeletePeerGroup(ctx context.Context, arg *api.DeletePeerGroupRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.DeletePeerGroup(&config.PeerGroup{Config: config.PeerGroupConfig{ - PeerGroupName: arg.Name, - }}) +func (s *Server) DeletePeerGroup(ctx context.Context, r *api.DeletePeerGroupRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeletePeerGroup(ctx, r) } -func (s *Server) UpdatePeerGroup(ctx context.Context, arg *api.UpdatePeerGroupRequest) (*api.UpdatePeerGroupResponse, error) { - c, err := NewPeerGroupFromAPIStruct(arg.PeerGroup) - if err != nil { - return nil, err - } - needsSoftResetIn, err := s.bgpServer.UpdatePeerGroup(c) +func (s *Server) UpdatePeerGroup(ctx context.Context, r *api.UpdatePeerGroupRequest) (*api.UpdatePeerGroupResponse, error) { + rsp, err := s.bgpServer.UpdatePeerGroup(ctx, r) if err != nil { return nil, err } - if arg.DoSoftResetIn && needsSoftResetIn { - return &api.UpdatePeerGroupResponse{NeedsSoftResetIn: false}, s.bgpServer.SoftResetIn("", bgp.RouteFamily(0)) + if r.DoSoftResetIn && rsp.NeedsSoftResetIn { + return &api.UpdatePeerGroupResponse{NeedsSoftResetIn: false}, s.bgpServer.ResetPeer(ctx, &api.ResetPeerRequest{ + Soft: true, + Direction: api.ResetPeerRequest_IN, + }) } - return &api.UpdatePeerGroupResponse{NeedsSoftResetIn: needsSoftResetIn}, nil + return rsp, err } -func (s *Server) AddDynamicNeighbor(ctx context.Context, arg *api.AddDynamicNeighborRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.AddDynamicNeighbor(&config.DynamicNeighbor{Config: config.DynamicNeighborConfig{ - Prefix: arg.DynamicNeighbor.Prefix, - PeerGroup: arg.DynamicNeighbor.PeerGroup, - }}) +func (s *Server) AddDynamicNeighbor(ctx context.Context, r *api.AddDynamicNeighborRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddDynamicNeighbor(ctx, r) } func NewPrefixFromApiStruct(a *api.Prefix) (*table.Prefix, error) { @@ -1787,71 +1576,11 @@ func NewDefinedSetFromApiStruct(a *api.DefinedSet) (table.DefinedSet, error) { var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) -func (s *Server) ListDefinedSet(arg *api.ListDefinedSetRequest, stream api.GobgpApi_ListDefinedSetServer) error { - cd, err := s.bgpServer.GetDefinedSet(table.DefinedType(arg.Type), arg.Name) +func (s *Server) ListDefinedSet(r *api.ListDefinedSetRequest, stream api.GobgpApi_ListDefinedSetServer) error { + sets, err := s.bgpServer.ListDefinedSet(context.Background(), r) if err != nil { return err } - sets := make([]*api.DefinedSet, 0) - for _, cs := range cd.PrefixSets { - ad := &api.DefinedSet{ - Type: api.DefinedType_PREFIX, - Name: cs.PrefixSetName, - Prefixes: func() []*api.Prefix { - l := make([]*api.Prefix, 0, len(cs.PrefixList)) - for _, p := range cs.PrefixList { - elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(p.MasklengthRange) - min, _ := strconv.ParseUint(elems[1], 10, 32) - max, _ := strconv.ParseUint(elems[2], 10, 32) - - l = append(l, &api.Prefix{IpPrefix: p.IpPrefix, MaskLengthMin: uint32(min), MaskLengthMax: uint32(max)}) - } - return l - }(), - } - sets = append(sets, ad) - - } - for _, cs := range cd.NeighborSets { - ad := &api.DefinedSet{ - Type: api.DefinedType_NEIGHBOR, - Name: cs.NeighborSetName, - List: cs.NeighborInfoList, - } - sets = append(sets, ad) - } - for _, cs := range cd.BgpDefinedSets.CommunitySets { - ad := &api.DefinedSet{ - Type: api.DefinedType_COMMUNITY, - Name: cs.CommunitySetName, - List: cs.CommunityList, - } - sets = append(sets, ad) - } - for _, cs := range cd.BgpDefinedSets.ExtCommunitySets { - ad := &api.DefinedSet{ - Type: api.DefinedType_EXT_COMMUNITY, - Name: cs.ExtCommunitySetName, - List: cs.ExtCommunityList, - } - sets = append(sets, ad) - } - for _, cs := range cd.BgpDefinedSets.LargeCommunitySets { - ad := &api.DefinedSet{ - Type: api.DefinedType_LARGE_COMMUNITY, - Name: cs.LargeCommunitySetName, - List: cs.LargeCommunityList, - } - sets = append(sets, ad) - } - for _, cs := range cd.BgpDefinedSets.AsPathSets { - ad := &api.DefinedSet{ - Type: api.DefinedType_AS_PATH, - Name: cs.AsPathSetName, - List: cs.AsPathList, - } - sets = append(sets, ad) - } for _, set := range sets { if err := stream.Send(&api.ListDefinedSetResponse{Set: set}); err != nil { return err @@ -1860,37 +1589,16 @@ func (s *Server) ListDefinedSet(arg *api.ListDefinedSetRequest, stream api.Gobgp return nil } -func (s *Server) AddDefinedSet(ctx context.Context, arg *api.AddDefinedSetRequest) (*empty.Empty, error) { - if arg == nil || arg.Set == nil { - return nil, fmt.Errorf("invalid request") - } - set, err := NewDefinedSetFromApiStruct(arg.Set) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.AddDefinedSet(set) +func (s *Server) AddDefinedSet(ctx context.Context, r *api.AddDefinedSetRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddDefinedSet(ctx, r) } -func (s *Server) DeleteDefinedSet(ctx context.Context, arg *api.DeleteDefinedSetRequest) (*empty.Empty, error) { - if arg == nil || arg.Set == nil { - return nil, fmt.Errorf("invalid request") - } - set, err := NewDefinedSetFromApiStruct(arg.Set) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.DeleteDefinedSet(set, arg.All) +func (s *Server) DeleteDefinedSet(ctx context.Context, r *api.DeleteDefinedSetRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeleteDefinedSet(ctx, r) } -func (s *Server) ReplaceDefinedSet(ctx context.Context, arg *api.ReplaceDefinedSetRequest) (*empty.Empty, error) { - if arg == nil || arg.Set == nil { - return nil, fmt.Errorf("invalid request") - } - set, err := NewDefinedSetFromApiStruct(arg.Set) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.ReplaceDefinedSet(set) +func (s *Server) ReplaceDefinedSet(ctx context.Context, r *api.ReplaceDefinedSetRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ReplaceDefinedSet(ctx, r) } func NewAPIStatementFromTableStruct(t *table.Statement) *api.Statement { @@ -2428,46 +2136,29 @@ func NewStatementFromApiStruct(a *api.Statement) (*table.Statement, error) { }, nil } -func (s *Server) ListStatement(arg *api.ListStatementRequest, stream api.GobgpApi_ListStatementServer) error { - for _, s := range s.bgpServer.GetStatement() { - if err := stream.Send(&api.ListStatementResponse{Statement: toStatementApi(s)}); err != nil { - return err +func (s *Server) ListStatement(r *api.ListStatementRequest, stream api.GobgpApi_ListStatementServer) error { + l, err := s.bgpServer.ListStatement(context.Background(), r) + if err != nil { + for _, st := range l { + err = stream.Send(&api.ListStatementResponse{Statement: st}) + if err != nil { + return err + } } } - return nil + return err } -func (s *Server) AddStatement(ctx context.Context, arg *api.AddStatementRequest) (*empty.Empty, error) { - if arg == nil || arg.Statement == nil { - return nil, fmt.Errorf("invalid request") - } - st, err := NewStatementFromApiStruct(arg.Statement) - if err == nil { - err = s.bgpServer.AddStatement(st) - } - return &empty.Empty{}, err +func (s *Server) AddStatement(ctx context.Context, r *api.AddStatementRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddStatement(ctx, r) } -func (s *Server) DeleteStatement(ctx context.Context, arg *api.DeleteStatementRequest) (*empty.Empty, error) { - if arg == nil || arg.Statement == nil { - return &empty.Empty{}, fmt.Errorf("invalid request") - } - st, err := NewStatementFromApiStruct(arg.Statement) - if err == nil { - err = s.bgpServer.DeleteStatement(st, arg.All) - } - return &empty.Empty{}, err +func (s *Server) DeleteStatement(ctx context.Context, r *api.DeleteStatementRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeleteStatement(ctx, r) } -func (s *Server) ReplaceStatement(ctx context.Context, arg *api.ReplaceStatementRequest) (*empty.Empty, error) { - if arg == nil || arg.Statement == nil { - return nil, fmt.Errorf("invalid request") - } - st, err := NewStatementFromApiStruct(arg.Statement) - if err == nil { - err = s.bgpServer.ReplaceStatement(st) - } - return &empty.Empty{}, err +func (s *Server) ReplaceStatement(ctx context.Context, r *api.ReplaceStatementRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ReplaceStatement(ctx, r) } func NewAPIPolicyFromTableStruct(p *table.Policy) *api.Policy { @@ -2587,46 +2278,26 @@ func NewRoaListFromTableStructList(origin []*table.ROA) []*api.Roa { return l } -func (s *Server) ListPolicy(arg *api.ListPolicyRequest, stream api.GobgpApi_ListPolicyServer) error { - for _, p := range s.bgpServer.GetPolicy() { - if err := stream.Send(&api.ListPolicyResponse{Policy: toPolicyApi(p)}); err != nil { +func (s *Server) ListPolicy(r *api.ListPolicyRequest, stream api.GobgpApi_ListPolicyServer) error { + l, err := s.bgpServer.ListPolicy(context.Background(), r) + for _, p := range l { + if err := stream.Send(&api.ListPolicyResponse{Policy: p}); err != nil { return err } } - return nil + return err } -func (s *Server) AddPolicy(ctx context.Context, arg *api.AddPolicyRequest) (*empty.Empty, error) { - if arg == nil || arg.Policy == nil { - return nil, fmt.Errorf("invalid request") - } - x, err := NewPolicyFromApiStruct(arg.Policy) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.AddPolicy(x, arg.ReferExistingStatements) +func (s *Server) AddPolicy(ctx context.Context, r *api.AddPolicyRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddPolicy(ctx, r) } -func (s *Server) DeletePolicy(ctx context.Context, arg *api.DeletePolicyRequest) (*empty.Empty, error) { - if arg == nil || arg.Policy == nil { - return &empty.Empty{}, fmt.Errorf("invalid request") - } - x, err := NewPolicyFromApiStruct(arg.Policy) - if err != nil { - return &empty.Empty{}, err - } - return &empty.Empty{}, s.bgpServer.DeletePolicy(x, arg.All, arg.PreserveStatements) +func (s *Server) DeletePolicy(ctx context.Context, r *api.DeletePolicyRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeletePolicy(ctx, r) } -func (s *Server) ReplacePolicy(ctx context.Context, arg *api.ReplacePolicyRequest) (*empty.Empty, error) { - if arg == nil || arg.Policy == nil { - return nil, fmt.Errorf("invalid request") - } - x, err := NewPolicyFromApiStruct(arg.Policy) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.ReplacePolicy(x, arg.ReferExistingStatements, arg.PreserveStatements) +func (s *Server) ReplacePolicy(ctx context.Context, r *api.ReplacePolicyRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ReplacePolicy(ctx, r) } func toPolicyAssignmentName(a *api.PolicyAssignment) (string, table.PolicyDirection, error) { @@ -2655,36 +2326,16 @@ func toPolicyAssignmentName(a *api.PolicyAssignment) (string, table.PolicyDirect } -func (s *Server) ListPolicyAssignment(arg *api.ListPolicyAssignmentRequest, stream api.GobgpApi_ListPolicyAssignmentServer) error { - if arg == nil || arg.Name == "" || arg.Direction == api.PolicyDirection_UNKNOWN { - return fmt.Errorf("invalid request") - } - dir := func() table.PolicyDirection { - if arg.Direction == api.PolicyDirection_EXPORT { - return table.POLICY_DIRECTION_EXPORT - } - return table.POLICY_DIRECTION_IMPORT - }() - - def, pols, err := s.bgpServer.GetPolicyAssignment(arg.Name, dir) - if err != nil { - return err - } - policies := make([]*table.Policy, 0, len(pols)) - for _, p := range pols { - t, err := table.NewPolicy(*p) - if err != nil { - return err +func (s *Server) ListPolicyAssignment(r *api.ListPolicyAssignmentRequest, stream api.GobgpApi_ListPolicyAssignmentServer) error { + l, err := s.bgpServer.ListPolicyAssignment(context.Background(), r) + if err == nil { + for _, a := range l { + if err := stream.Send(&api.ListPolicyAssignmentResponse{Assignment: a}); err != nil { + return err + } } - policies = append(policies, t) - } - t := &table.PolicyAssignment{ - Name: arg.Name, - Type: dir, - Default: def, - Policies: policies, } - return stream.Send(&api.ListPolicyAssignmentResponse{Assignment: NewAPIPolicyAssignmentFromTableStruct(t)}) + return err } func defaultRouteType(d api.RouteAction) table.RouteType { @@ -2706,50 +2357,20 @@ func toPolicyDefinition(policies []*api.Policy) []*config.PolicyDefinition { return l } -func (s *Server) AddPolicyAssignment(ctx context.Context, arg *api.AddPolicyAssignmentRequest) (*empty.Empty, error) { - if arg == nil || arg.Assignment == nil { - return nil, fmt.Errorf("invalid request") - } - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.AddPolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), defaultRouteType(arg.Assignment.Default)) +func (s *Server) AddPolicyAssignment(ctx context.Context, r *api.AddPolicyAssignmentRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.AddPolicyAssignment(ctx, r) } -func (s *Server) DeletePolicyAssignment(ctx context.Context, arg *api.DeletePolicyAssignmentRequest) (*empty.Empty, error) { - if arg == nil || arg.Assignment == nil { - return nil, fmt.Errorf("invalid request") - } - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.DeletePolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), arg.All) +func (s *Server) DeletePolicyAssignment(ctx context.Context, r *api.DeletePolicyAssignmentRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.DeletePolicyAssignment(ctx, r) } -func (s *Server) ReplacePolicyAssignment(ctx context.Context, arg *api.ReplacePolicyAssignmentRequest) (*empty.Empty, error) { - if arg == nil || arg.Assignment == nil { - return nil, fmt.Errorf("invalid request") - } - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - return &empty.Empty{}, s.bgpServer.ReplacePolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), defaultRouteType(arg.Assignment.Default)) +func (s *Server) ReplacePolicyAssignment(ctx context.Context, r *api.ReplacePolicyAssignmentRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.ReplacePolicyAssignment(ctx, r) } -func (s *Server) GetBgp(ctx context.Context, arg *api.GetBgpRequest) (*api.GetBgpResponse, error) { - g := s.bgpServer.GetServer() - return &api.GetBgpResponse{ - Global: &api.Global{ - As: g.Config.As, - RouterId: g.Config.RouterId, - ListenPort: g.Config.Port, - ListenAddresses: g.Config.LocalAddressList, - UseMultiplePaths: g.UseMultiplePaths.Config.Enabled, - }, - }, nil +func (s *Server) GetBgp(ctx context.Context, r *api.GetBgpRequest) (*api.GetBgpResponse, error) { + return s.bgpServer.GetBgp(ctx, r) } func NewGlobalFromAPIStruct(a *api.Global) *config.Global { @@ -2880,51 +2501,14 @@ func NewGlobalFromConfigStruct(c *config.Global) *api.Global { } } -func (s *Server) StartBgp(ctx context.Context, arg *api.StartBgpRequest) (*empty.Empty, error) { - if arg == nil || arg.Global == nil { - return &empty.Empty{}, fmt.Errorf("invalid request") - } - g := arg.Global - if net.ParseIP(g.RouterId) == nil { - return nil, fmt.Errorf("invalid router-id format: %s", g.RouterId) - } - - global := NewGlobalFromAPIStruct(arg.Global) - - return &empty.Empty{}, s.bgpServer.Start(global) +func (s *Server) StartBgp(ctx context.Context, r *api.StartBgpRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.StartBgp(ctx, r) } -func (s *Server) StopBgp(ctx context.Context, arg *api.StopBgpRequest) (*empty.Empty, error) { - return &empty.Empty{}, s.bgpServer.Stop() +func (s *Server) StopBgp(ctx context.Context, r *api.StopBgpRequest) (*empty.Empty, error) { + return &empty.Empty{}, s.bgpServer.StopBgp(ctx, r) } -func (s *Server) GetTable(ctx context.Context, arg *api.GetTableRequest) (*api.GetTableResponse, error) { - if arg == nil || arg.Name == "" { - return nil, fmt.Errorf("invalid request") - } - family := bgp.RouteFamily(arg.Family) - var in bool - var err error - var info *table.TableInfo - switch arg.Type { - case api.Resource_GLOBAL, api.Resource_LOCAL: - info, err = s.bgpServer.GetRibInfo(arg.Name, family) - case api.Resource_ADJ_IN: - in = true - fallthrough - case api.Resource_ADJ_OUT: - info, err = s.bgpServer.GetAdjRibInfo(arg.Name, family, in) - default: - return nil, fmt.Errorf("unsupported resource type: %s", arg.Type) - } - - if err != nil { - return nil, err - } - - return &api.GetTableResponse{ - NumDestination: uint64(info.NumDestination), - NumPath: uint64(info.NumPath), - NumAccepted: uint64(info.NumAccepted), - }, nil +func (s *Server) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.GetTableResponse, error) { + return s.bgpServer.GetTable(ctx, r) } diff --git a/pkg/server/server.go b/pkg/server/server.go index 6dbcc013..52624b97 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -17,14 +17,19 @@ package server import ( "bytes" + "context" "fmt" "net" "strconv" "sync" "time" + api "github.com/osrg/gobgp/api" + + "github.com/osrg/gobgp/internal/pkg/apiutil" "github.com/osrg/gobgp/internal/pkg/config" "github.com/osrg/gobgp/internal/pkg/table" + "github.com/osrg/gobgp/internal/pkg/zebra" "github.com/osrg/gobgp/pkg/packet/bgp" "github.com/eapache/channels" @@ -650,7 +655,7 @@ func (server *BgpServer) notifyBestWatcher(best []*table.Path, multipath [][]*ta server.notifyWatcher(WATCH_EVENT_TYPE_BEST_PATH, w) } -func (s *BgpServer) ToConfig(peer *Peer, getAdvertised bool) *config.Neighbor { +func (s *BgpServer) toConfig(peer *Peer, getAdvertised bool) *config.Neighbor { // create copy which can be access to without mutex peer.fsm.lock.RLock() conf := *peer.fsm.pConf @@ -733,7 +738,7 @@ func (server *BgpServer) notifyPrePolicyUpdateWatcher(peer *Peer, pathList []*ta Payload: payload, PostPolicy: false, PathList: cloned, - Neighbor: server.ToConfig(peer, false), + Neighbor: server.toConfig(peer, false), } peer.fsm.lock.RUnlock() server.notifyWatcher(WATCH_EVENT_TYPE_PRE_UPDATE, ev) @@ -761,7 +766,7 @@ func (server *BgpServer) notifyPostPolicyUpdateWatcher(peer *Peer, pathList []*t Timestamp: cloned[0].GetTimestamp(), PostPolicy: true, PathList: cloned, - Neighbor: server.ToConfig(peer, false), + Neighbor: server.toConfig(peer, false), } peer.fsm.lock.RUnlock() server.notifyWatcher(WATCH_EVENT_TYPE_POST_UPDATE, ev) @@ -1539,65 +1544,85 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { } } -func (s *BgpServer) AddCollector(c *config.CollectorConfig) error { - return s.mgmtOperation(func() error { - _, err := NewCollector(s, c.Url, c.DbName, c.TableDumpInterval) - return err - }, false) -} - -func (s *BgpServer) StartZebraClient(c *config.ZebraConfig) error { +func (s *BgpServer) EnableZebra(ctx context.Context, r *api.EnableZebraRequest) error { return s.mgmtOperation(func() error { if s.zclient != nil { return fmt.Errorf("already connected to Zebra") } - protos := make([]string, 0, len(c.RedistributeRouteTypeList)) - for _, p := range c.RedistributeRouteTypeList { + + for _, p := range r.RouteTypes { + if _, err := zebra.RouteTypeFromString(p); err != nil { + return err + } + } + + protos := make([]string, 0, len(r.RouteTypes)) + for _, p := range r.RouteTypes { protos = append(protos, string(p)) } var err error - s.zclient, err = newZebraClient(s, c.Url, protos, c.Version, c.NexthopTriggerEnable, c.NexthopTriggerDelay) + s.zclient, err = newZebraClient(s, r.Url, protos, uint8(r.Version), r.NexthopTriggerEnable, uint8(r.NexthopTriggerDelay)) return err }, false) } -func (s *BgpServer) AddBmp(c *config.BmpServerConfig) error { +func (s *BgpServer) AddBmp(ctx context.Context, r *api.AddBmpRequest) error { return s.mgmtOperation(func() error { - return s.bmpManager.addServer(c) + t, ok := api.AddBmpRequest_MonitoringPolicy_name[int32(r.Type)] + if !ok { + return fmt.Errorf("invalid bmp route monitoring policy: %v", r.Type) + } + return s.bmpManager.addServer(&config.BmpServerConfig{ + Address: r.Address, + Port: r.Port, + RouteMonitoringPolicy: config.BmpRouteMonitoringPolicyType(t), + }) }, true) } -func (s *BgpServer) DeleteBmp(c *config.BmpServerConfig) error { +func (s *BgpServer) DeleteBmp(ctx context.Context, r *api.DeleteBmpRequest) error { return s.mgmtOperation(func() error { - return s.bmpManager.deleteServer(c) + return s.bmpManager.deleteServer(&config.BmpServerConfig{ + Address: r.Address, + Port: r.Port, + }) }, true) } -func (s *BgpServer) Shutdown() { +func (s *BgpServer) StopBgp(ctx context.Context, r *api.StopBgpRequest) error { s.mgmtOperation(func() error { s.shutdownWG = new(sync.WaitGroup) s.shutdownWG.Add(1) - stateOp := AdminStateOperation{ - State: ADMIN_STATE_DOWN, - Communication: nil, + + for k := range s.neighborMap { + if err := s.deleteNeighbor(&config.Neighbor{Config: config.NeighborConfig{ + NeighborAddress: k}}, bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_PEER_DECONFIGURED); err != nil { + return err + } } - for _, p := range s.neighborMap { - p.fsm.adminStateCh <- stateOp + for _, l := range s.listeners { + l.Close() } - // TODO: call fsmincomingCh.Close() + s.bgpConfig.Global = config.Global{} return nil }, false) // Waits for all goroutines per peer to stop. // Note: This should not be wrapped with s.mgmtOperation() in order to // avoid the deadlock in the main goroutine of BgpServer. - if s.shutdownWG != nil { - s.shutdownWG.Wait() - s.shutdownWG = nil - } + // if s.shutdownWG != nil { + // s.shutdownWG.Wait() + // s.shutdownWG = nil + // } + return nil } -func (s *BgpServer) UpdatePolicy(policy config.RoutingPolicy) error { +func (s *BgpServer) UpdatePolicy(ctx context.Context, r *api.UpdatePolicyRequest) error { + rp, err := NewRoutingPolicyFromApiStruct(r) + if err != nil { + return err + } + return s.mgmtOperation(func() error { ap := make(map[string]config.ApplyPolicy, len(s.neighborMap)+1) ap[table.GLOBAL_RIB_NAME] = s.bgpConfig.Global.ApplyPolicy @@ -1610,7 +1635,7 @@ func (s *BgpServer) UpdatePolicy(policy config.RoutingPolicy) error { ap[peer.ID()] = peer.fsm.pConf.ApplyPolicy peer.fsm.lock.RUnlock() } - return s.policy.Reset(&policy, ap) + return s.policy.Reset(rp, ap) }, false) } @@ -1755,30 +1780,54 @@ func pathTokey(path *table.Path) string { return fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.GetNlri().String()) } -func (s *BgpServer) AddPath(vrfId string, pathList []*table.Path) (uuidBytes []byte, err error) { - err = s.mgmtOperation(func() error { - if err := s.fixupApiPath(vrfId, pathList); err != nil { +func (s *BgpServer) addPathList(vrfId string, pathList []*table.Path) error { + err := s.fixupApiPath(vrfId, pathList) + if err == nil { + s.propagateUpdate(nil, pathList) + } + return err +} + +func (s *BgpServer) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.AddPathResponse, error) { + var uuidBytes []byte + err := s.mgmtOperation(func() error { + pathList, err := api2PathList(r.Resource, []*api.Path{r.Path}) + if err != nil { return err } - if len(pathList) == 1 { - path := pathList[0] - id, _ := uuid.NewV4() - s.uuidMap[id] = pathTokey(path) - uuidBytes = id.Bytes() + err = s.addPathList(r.VrfId, pathList) + if err != nil { + return err } - s.propagateUpdate(nil, pathList) + path := pathList[0] + id, _ := uuid.NewV4() + s.uuidMap[id] = pathTokey(path) + uuidBytes = id.Bytes() return nil }, true) - return + return &api.AddPathResponse{Uuid: uuidBytes}, err } -func (s *BgpServer) DeletePath(uuidBytes []byte, f bgp.RouteFamily, vrfId string, pathList []*table.Path) error { +func (s *BgpServer) DeletePath(ctx context.Context, r *api.DeletePathRequest) error { return s.mgmtOperation(func() error { deletePathList := make([]*table.Path, 0) - if len(uuidBytes) > 0 { + + pathList, err := func() ([]*table.Path, error) { + if r.Path != nil { + r.Path.IsWithdraw = true + return api2PathList(r.Resource, []*api.Path{r.Path}) + } + return []*table.Path{}, nil + }() + if err != nil { + return err + } + f := bgp.RouteFamily(r.Family) + + if len(r.Uuid) > 0 { // Delete locally generated path which has the given UUID path := func() *table.Path { - id, _ := uuid.FromBytes(uuidBytes) + id, _ := uuid.FromBytes(r.Uuid) if key, ok := s.uuidMap[id]; !ok { return nil } else { @@ -1808,7 +1857,7 @@ func (s *BgpServer) DeletePath(uuidBytes []byte, f bgp.RouteFamily, vrfId string } s.uuidMap = make(map[uuid.UUID]string) } else { - if err := s.fixupApiPath(vrfId, pathList); err != nil { + if err := s.fixupApiPath(r.VrfId, pathList); err != nil { return err } deletePathList = pathList @@ -1818,7 +1867,7 @@ func (s *BgpServer) DeletePath(uuidBytes []byte, f bgp.RouteFamily, vrfId string }, true) } -func (s *BgpServer) UpdatePath(vrfId string, pathList []*table.Path) error { +func (s *BgpServer) updatePath(vrfId string, pathList []*table.Path) error { err := s.mgmtOperation(func() error { if err := s.fixupApiPath(vrfId, pathList); err != nil { return err @@ -1829,8 +1878,17 @@ func (s *BgpServer) UpdatePath(vrfId string, pathList []*table.Path) error { return err } -func (s *BgpServer) Start(c *config.Global) error { +func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Global == nil { + return fmt.Errorf("invalid request") + } + g := r.Global + if net.ParseIP(g.RouterId) == nil { + return fmt.Errorf("invalid router-id format: %s", g.RouterId) + } + + c := NewGlobalFromAPIStruct(g) if err := config.SetDefaultGlobalConfigValues(c); err != nil { return err } @@ -1864,7 +1922,8 @@ func (s *BgpServer) Start(c *config.Global) error { }, false) } -func (s *BgpServer) GetVrf() (l []*table.Vrf) { +// TODO: delete this function +func (s *BgpServer) listVrf() (l []*table.Vrf) { s.mgmtOperation(func() error { l = make([]*table.Vrf, 0, len(s.globalRib.Vrfs)) for _, vrf := range s.globalRib.Vrfs { @@ -1875,8 +1934,48 @@ func (s *BgpServer) GetVrf() (l []*table.Vrf) { return l } -func (s *BgpServer) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInterface, im, ex []bgp.ExtendedCommunityInterface) error { +func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest) (l []*api.Vrf) { + toApi := func(v *table.Vrf) *api.Vrf { + return &api.Vrf{ + Name: v.Name, + Rd: apiutil.MarshalRD(v.Rd), + Id: v.Id, + ImportRt: apiutil.MarshalRTs(v.ImportRt), + ExportRt: apiutil.MarshalRTs(v.ExportRt), + } + } + s.mgmtOperation(func() error { + l = make([]*api.Vrf, 0, len(s.globalRib.Vrfs)) + for _, vrf := range s.globalRib.Vrfs { + l = append(l, toApi(vrf.Clone())) + } + return nil + }, true) + return l +} + +func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Vrf == nil { + return fmt.Errorf("invalid request") + } + + name := r.Vrf.Name + id := r.Vrf.Id + + rd, err := apiutil.UnmarshalRD(r.Vrf.Rd) + if err != nil { + return err + } + im, err := apiutil.UnmarshalRTs(r.Vrf.ImportRt) + if err != nil { + return err + } + ex, err := apiutil.UnmarshalRTs(r.Vrf.ExportRt) + if err != nil { + return err + } + pi := &table.PeerInfo{ AS: s.bgpConfig.Global.Config.As, LocalID: net.ParseIP(s.bgpConfig.Global.Config.RouterId).To4(), @@ -1890,8 +1989,12 @@ func (s *BgpServer) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInte }, true) } -func (s *BgpServer) DeleteVrf(name string) error { +func (s *BgpServer) DeleteVrf(ctx context.Context, r *api.DeleteVrfRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Name == "" { + return fmt.Errorf("invalid request") + } + name := r.Name for _, n := range s.neighborMap { n.fsm.lock.RLock() peerVrf := n.fsm.pConf.Config.Vrf @@ -1911,22 +2014,6 @@ func (s *BgpServer) DeleteVrf(name string) error { }, true) } -func (s *BgpServer) Stop() error { - return s.mgmtOperation(func() error { - for k := range s.neighborMap { - if err := s.deleteNeighbor(&config.Neighbor{Config: config.NeighborConfig{ - NeighborAddress: k}}, bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_PEER_DECONFIGURED); err != nil { - return err - } - } - for _, l := range s.listeners { - l.Close() - } - s.bgpConfig.Global = config.Global{} - return nil - }, true) -} - func familiesForSoftreset(peer *Peer, family bgp.RouteFamily) []bgp.RouteFamily { if family == bgp.RouteFamily(0) { configured := peer.configuredRFlist() @@ -2037,38 +2124,32 @@ func (s *BgpServer) softResetOut(addr string, family bgp.RouteFamily, deferral b return nil } -func (s *BgpServer) SoftResetIn(addr string, family bgp.RouteFamily) error { - return s.mgmtOperation(func() error { - log.WithFields(log.Fields{ - "Topic": "Operation", - "Key": addr, - }).Info("Neighbor soft reset in") - return s.softResetIn(addr, family) - }, true) +func (s *BgpServer) sResetIn(addr string, family bgp.RouteFamily) error { + log.WithFields(log.Fields{ + "Topic": "Operation", + "Key": addr, + }).Info("Neighbor soft reset in") + return s.softResetIn(addr, family) } -func (s *BgpServer) SoftResetOut(addr string, family bgp.RouteFamily) error { - return s.mgmtOperation(func() error { - log.WithFields(log.Fields{ - "Topic": "Operation", - "Key": addr, - }).Info("Neighbor soft reset out") - return s.softResetOut(addr, family, false) - }, true) +func (s *BgpServer) sResetOut(addr string, family bgp.RouteFamily) error { + log.WithFields(log.Fields{ + "Topic": "Operation", + "Key": addr, + }).Info("Neighbor soft reset out") + return s.softResetOut(addr, family, false) } -func (s *BgpServer) SoftReset(addr string, family bgp.RouteFamily) error { - return s.mgmtOperation(func() error { - log.WithFields(log.Fields{ - "Topic": "Operation", - "Key": addr, - }).Info("Neighbor soft reset") - err := s.softResetIn(addr, family) - if err != nil { - return err - } - return s.softResetOut(addr, family, false) - }, true) +func (s *BgpServer) sReset(addr string, family bgp.RouteFamily) error { + log.WithFields(log.Fields{ + "Topic": "Operation", + "Key": addr, + }).Info("Neighbor soft reset") + err := s.softResetIn(addr, family) + if err != nil { + return err + } + return s.softResetOut(addr, family, false) } func (s *BgpServer) validateTable(r *table.Table) (v []*table.Validation) { @@ -2083,7 +2164,7 @@ func (s *BgpServer) validateTable(r *table.Table) (v []*table.Validation) { return } -func (s *BgpServer) GetRib(addr string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (rib *table.Table, v []*table.Validation, err error) { +func (s *BgpServer) getRib(addr string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (rib *table.Table, v []*table.Validation, err error) { err = s.mgmtOperation(func() error { m := s.globalRib id := table.GLOBAL_RIB_NAME @@ -2112,7 +2193,7 @@ func (s *BgpServer) GetRib(addr string, family bgp.RouteFamily, prefixes []*tabl return } -func (s *BgpServer) GetVrfRib(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (rib *table.Table, err error) { +func (s *BgpServer) getVrfRib(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (rib *table.Table, err error) { err = s.mgmtOperation(func() error { m := s.globalRib vrfs := m.Vrfs @@ -2138,7 +2219,7 @@ func (s *BgpServer) GetVrfRib(name string, family bgp.RouteFamily, prefixes []*t return } -func (s *BgpServer) GetAdjRib(addr string, family bgp.RouteFamily, in bool, prefixes []*table.LookupPrefix) (rib *table.Table, v []*table.Validation, err error) { +func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, prefixes []*table.LookupPrefix) (rib *table.Table, v []*table.Validation, err error) { err = s.mgmtOperation(func() error { peer, ok := s.neighborMap[addr] if !ok { @@ -2162,7 +2243,69 @@ func (s *BgpServer) GetAdjRib(addr string, family bgp.RouteFamily, in bool, pref return } -func (s *BgpServer) GetRibInfo(addr string, family bgp.RouteFamily) (info *table.TableInfo, err error) { +func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest) ([]*api.Destination, error) { + var dsts []*api.Destination + var tbl *table.Table + var v []*table.Validation + + f := func() []*table.LookupPrefix { + l := make([]*table.LookupPrefix, 0, len(r.Prefixes)) + for _, p := range r.Prefixes { + l = append(l, &table.LookupPrefix{ + Prefix: p.Prefix, + LookupOption: table.LookupOption(p.LookupOption), + }) + } + return l + } + + in := false + family := bgp.RouteFamily(r.Family) + var err error + switch r.Type { + case api.Resource_LOCAL, api.Resource_GLOBAL: + tbl, v, err = s.getRib(r.Name, family, f()) + case api.Resource_ADJ_IN: + in = true + fallthrough + case api.Resource_ADJ_OUT: + tbl, v, err = s.getAdjRib(r.Name, family, in, f()) + case api.Resource_VRF: + tbl, err = s.getVrfRib(r.Name, family, []*table.LookupPrefix{}) + default: + return nil, fmt.Errorf("unsupported resource type: %v", r.Type) + } + + if err != nil { + return nil, err + } + + idx := 0 + err = func() error { + for _, dst := range tbl.GetDestinations() { + d := api.Destination{ + Prefix: dst.GetNlri().String(), + Paths: make([]*api.Path, 0, len(dst.GetAllKnownPathList())), + } + for i, path := range dst.GetAllKnownPathList() { + p := ToPathApi(path, getValidation(v, idx)) + idx++ + if i == 0 && !table.SelectionOptions.DisableBestPathSelection { + switch r.Type { + case api.Resource_LOCAL, api.Resource_GLOBAL: + p.Best = true + } + } + d.Paths = append(d.Paths, p) + } + dsts = append(dsts, &d) + } + return nil + }() + return dsts, err +} + +func (s *BgpServer) getRibInfo(addr string, family bgp.RouteFamily) (info *table.TableInfo, err error) { err = s.mgmtOperation(func() error { m := s.globalRib id := table.GLOBAL_RIB_NAME @@ -2185,7 +2328,7 @@ func (s *BgpServer) GetRibInfo(addr string, family bgp.RouteFamily) (info *table return } -func (s *BgpServer) GetAdjRibInfo(addr string, family bgp.RouteFamily, in bool) (info *table.TableInfo, err error) { +func (s *BgpServer) getAdjRibInfo(addr string, family bgp.RouteFamily, in bool) (info *table.TableInfo, err error) { err = s.mgmtOperation(func() error { peer, ok := s.neighborMap[addr] if !ok { @@ -2206,16 +2349,57 @@ func (s *BgpServer) GetAdjRibInfo(addr string, family bgp.RouteFamily, in bool) return } -func (s *BgpServer) GetServer() (c *config.Global) { +func (s *BgpServer) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.GetTableResponse, error) { + if r == nil || r.Name == "" { + return nil, fmt.Errorf("invalid request") + } + family := bgp.RouteFamily(r.Family) + var in bool + var err error + var info *table.TableInfo + switch r.Type { + case api.Resource_GLOBAL, api.Resource_LOCAL: + info, err = s.getRibInfo(r.Name, family) + case api.Resource_ADJ_IN: + in = true + fallthrough + case api.Resource_ADJ_OUT: + info, err = s.getAdjRibInfo(r.Name, family, in) + default: + return nil, fmt.Errorf("unsupported resource type: %s", r.Type) + } + + if err != nil { + return nil, err + } + + return &api.GetTableResponse{ + NumDestination: uint64(info.NumDestination), + NumPath: uint64(info.NumPath), + NumAccepted: uint64(info.NumAccepted), + }, nil +} + +func (s *BgpServer) GetBgp(ctx context.Context, r *api.GetBgpRequest) (*api.GetBgpResponse, error) { + var rsp *api.GetBgpResponse s.mgmtOperation(func() error { g := s.bgpConfig.Global - c = &g + rsp = &api.GetBgpResponse{ + Global: &api.Global{ + As: g.Config.As, + RouterId: g.Config.RouterId, + ListenPort: g.Config.Port, + ListenAddresses: g.Config.LocalAddressList, + UseMultiplePaths: g.UseMultiplePaths.Config.Enabled, + }, + } return nil }, false) - return c + return rsp, nil } -func (s *BgpServer) GetNeighbor(address string, getAdvertised bool) (l []*config.Neighbor) { +func (s *BgpServer) getNeighbor(address string, getAdvertised bool) []*config.Neighbor { + var l []*config.Neighbor s.mgmtOperation(func() error { l = make([]*config.Neighbor, 0, len(s.neighborMap)) for k, peer := range s.neighborMap { @@ -2225,13 +2409,35 @@ func (s *BgpServer) GetNeighbor(address string, getAdvertised bool) (l []*config if address != "" && address != k && address != neighborIface { continue } - l = append(l, s.ToConfig(peer, getAdvertised)) + // FIXME: should remove toConfig() conversion + l = append(l, s.toConfig(peer, getAdvertised)) } return nil }, false) return l } +func (s *BgpServer) ListPeer(ctx context.Context, r *api.ListPeerRequest) ([]*api.Peer, error) { + var l []*api.Peer + s.mgmtOperation(func() error { + address := r.Address + getAdvertised := r.EnableAdvertised + l = make([]*api.Peer, 0, len(s.neighborMap)) + for k, peer := range s.neighborMap { + peer.fsm.lock.RLock() + neighborIface := peer.fsm.pConf.Config.NeighborInterface + peer.fsm.lock.RUnlock() + if address != "" && address != k && address != neighborIface { + continue + } + // FIXME: should remove toConfig() conversion + l = append(l, NewPeerFromConfigStruct(s.toConfig(peer, getAdvertised))) + } + return nil + }, false) + return l, nil +} + func (server *BgpServer) addPeerGroup(c *config.PeerGroup) error { name := c.Config.PeerGroupName if _, y := server.peerGroupMap[name]; y { @@ -2322,28 +2528,38 @@ func (server *BgpServer) addNeighbor(c *config.Neighbor) error { return nil } -func (s *BgpServer) AddPeerGroup(c *config.PeerGroup) error { +func (s *BgpServer) AddPeerGroup(ctx context.Context, r *api.AddPeerGroupRequest) error { return s.mgmtOperation(func() error { + c, err := NewPeerGroupFromAPIStruct(r.PeerGroup) + if err != nil { + return err + } return s.addPeerGroup(c) }, true) } -func (s *BgpServer) AddNeighbor(c *config.Neighbor) error { +func (s *BgpServer) AddPeer(ctx context.Context, r *api.AddPeerRequest) error { return s.mgmtOperation(func() error { + c, err := NewNeighborFromAPIStruct(r.Peer) + if err != nil { + return err + } return s.addNeighbor(c) }, true) } -func (s *BgpServer) AddDynamicNeighbor(c *config.DynamicNeighbor) error { +func (s *BgpServer) AddDynamicNeighbor(ctx context.Context, r *api.AddDynamicNeighborRequest) error { return s.mgmtOperation(func() error { + c := &config.DynamicNeighbor{Config: config.DynamicNeighborConfig{ + Prefix: r.DynamicNeighbor.Prefix, + PeerGroup: r.DynamicNeighbor.PeerGroup}, + } s.peerGroupMap[c.Config.PeerGroup].AddDynamicNeighbor(c) return nil }, true) } -func (server *BgpServer) deletePeerGroup(pg *config.PeerGroup) error { - name := pg.Config.PeerGroupName - +func (server *BgpServer) deletePeerGroup(name string) error { if _, y := server.peerGroupMap[name]; !y { return fmt.Errorf("Can't delete a peer-group %s which does not exist", name) } @@ -2402,9 +2618,9 @@ func (server *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) return nil } -func (s *BgpServer) DeletePeerGroup(c *config.PeerGroup) error { +func (s *BgpServer) DeletePeerGroup(ctx context.Context, r *api.DeletePeerGroupRequest) error { return s.mgmtOperation(func() error { - name := c.Config.PeerGroupName + name := r.Name for _, n := range s.neighborMap { n.fsm.lock.RLock() peerGroup := n.fsm.pConf.Config.PeerGroup @@ -2413,12 +2629,16 @@ func (s *BgpServer) DeletePeerGroup(c *config.PeerGroup) error { return fmt.Errorf("failed to delete peer-group %s: neighbor %s is in use", name, n.ID()) } } - return s.deletePeerGroup(c) + return s.deletePeerGroup(name) }, true) } -func (s *BgpServer) DeleteNeighbor(c *config.Neighbor) error { +func (s *BgpServer) DeletePeer(ctx context.Context, r *api.DeletePeerRequest) error { return s.mgmtOperation(func() error { + c := &config.Neighbor{Config: config.NeighborConfig{ + NeighborAddress: r.Address, + NeighborInterface: r.Interface, + }} return s.deleteNeighbor(c, bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_PEER_DECONFIGURED) }, true) } @@ -2443,12 +2663,17 @@ func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool return needsSoftResetIn, nil } -func (s *BgpServer) UpdatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) { +func (s *BgpServer) UpdatePeerGroup(ctx context.Context, r *api.UpdatePeerGroupRequest) (rsp *api.UpdatePeerGroupResponse, err error) { + doSoftreset := false err = s.mgmtOperation(func() error { - needsSoftResetIn, err = s.updatePeerGroup(pg) + pg, err := NewPeerGroupFromAPIStruct(r.PeerGroup) + if err != nil { + return err + } + doSoftreset, err = s.updatePeerGroup(pg) return err }, true) - return needsSoftResetIn, err + return &api.UpdatePeerGroupResponse{NeedsSoftResetIn: doSoftreset}, err } func (s *BgpServer) updateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) { @@ -2546,12 +2771,17 @@ func (s *BgpServer) updateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, e return needsSoftResetIn, err } -func (s *BgpServer) UpdateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) { +func (s *BgpServer) UpdateNeighbor(ctx context.Context, r *api.UpdatePeerRequest) (rsp *api.UpdatePeerResponse, err error) { + doSoftReset := false err = s.mgmtOperation(func() error { - needsSoftResetIn, err = s.updateNeighbor(c) + c, err := NewNeighborFromAPIStruct(r.Peer) + if err != nil { + return err + } + doSoftReset, err = s.updateNeighbor(c) return err }, true) - return needsSoftResetIn, err + return &api.UpdatePeerResponse{NeedsSoftResetIn: doSoftReset}, err } func (s *BgpServer) addrToPeers(addr string) (l []*Peer, err error) { @@ -2568,7 +2798,7 @@ func (s *BgpServer) addrToPeers(addr string) (l []*Peer, err error) { return []*Peer{peer}, nil } -func (s *BgpServer) resetNeighbor(op, addr string, subcode uint8, data []byte) error { +func (s *BgpServer) sendNotification(op, addr string, subcode uint8, data []byte) error { log.WithFields(log.Fields{ "Topic": "Operation", "Key": addr, @@ -2584,15 +2814,36 @@ func (s *BgpServer) resetNeighbor(op, addr string, subcode uint8, data []byte) e return err } -func (s *BgpServer) ShutdownNeighbor(addr, communication string) error { +func (s *BgpServer) ShutdownPeer(ctx context.Context, r *api.ShutdownPeerRequest) error { return s.mgmtOperation(func() error { - return s.resetNeighbor("Neighbor shutdown", addr, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, newAdministrativeCommunication(communication)) + return s.sendNotification("Neighbor shutdown", r.Address, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, newAdministrativeCommunication(r.Communication)) }, true) } -func (s *BgpServer) ResetNeighbor(addr, communication string) error { +func (s *BgpServer) ResetPeer(ctx context.Context, r *api.ResetPeerRequest) error { return s.mgmtOperation(func() error { - err := s.resetNeighbor("Neighbor reset", addr, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, newAdministrativeCommunication(communication)) + addr := r.Address + comm := r.Communication + if r.Soft { + var err error + if addr == "all" { + addr = "" + } + family := bgp.RouteFamily(0) + switch r.Direction { + case api.ResetPeerRequest_IN: + err = s.sResetIn(addr, family) + case api.ResetPeerRequest_OUT: + err = s.sResetOut(addr, family) + case api.ResetPeerRequest_BOTH: + err = s.sReset(addr, family) + default: + err = fmt.Errorf("unknown direction") + } + return err + } + + err := s.sendNotification("Neighbor reset", addr, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET, newAdministrativeCommunication(comm)) if err != nil { return err } @@ -2636,41 +2887,127 @@ func (s *BgpServer) setAdminState(addr, communication string, enable bool) error return nil } -func (s *BgpServer) EnableNeighbor(addr string) error { +func (s *BgpServer) EnableNeighbor(ctx context.Context, r *api.EnablePeerRequest) error { return s.mgmtOperation(func() error { - return s.setAdminState(addr, "", true) + return s.setAdminState(r.Address, "", true) }, true) } -func (s *BgpServer) DisableNeighbor(addr, communication string) error { +func (s *BgpServer) DisableNeighbor(ctx context.Context, r *api.DisablePeerRequest) error { return s.mgmtOperation(func() error { - return s.setAdminState(addr, communication, false) + return s.setAdminState(r.Address, r.Communication, false) }, true) } -func (s *BgpServer) GetDefinedSet(typ table.DefinedType, name string) (sets *config.DefinedSets, err error) { +func (s *BgpServer) ListDefinedSet(ctx context.Context, r *api.ListDefinedSetRequest) (sets []*api.DefinedSet, err error) { + var cd *config.DefinedSets err = s.mgmtOperation(func() error { - sets, err = s.policy.GetDefinedSet(typ, name) - return nil + cd, err = s.policy.GetDefinedSet(table.DefinedType(r.Type), r.Name) + return err }, false) - return sets, err + + if err != nil { + return nil, err + } + sets = make([]*api.DefinedSet, 0) + for _, cs := range cd.PrefixSets { + ad := &api.DefinedSet{ + Type: api.DefinedType_PREFIX, + Name: cs.PrefixSetName, + Prefixes: func() []*api.Prefix { + l := make([]*api.Prefix, 0, len(cs.PrefixList)) + for _, p := range cs.PrefixList { + elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(p.MasklengthRange) + min, _ := strconv.ParseUint(elems[1], 10, 32) + max, _ := strconv.ParseUint(elems[2], 10, 32) + + l = append(l, &api.Prefix{IpPrefix: p.IpPrefix, MaskLengthMin: uint32(min), MaskLengthMax: uint32(max)}) + } + return l + }(), + } + sets = append(sets, ad) + + } + for _, cs := range cd.NeighborSets { + ad := &api.DefinedSet{ + Type: api.DefinedType_NEIGHBOR, + Name: cs.NeighborSetName, + List: cs.NeighborInfoList, + } + sets = append(sets, ad) + } + for _, cs := range cd.BgpDefinedSets.CommunitySets { + ad := &api.DefinedSet{ + Type: api.DefinedType_COMMUNITY, + Name: cs.CommunitySetName, + List: cs.CommunityList, + } + sets = append(sets, ad) + } + for _, cs := range cd.BgpDefinedSets.ExtCommunitySets { + ad := &api.DefinedSet{ + Type: api.DefinedType_EXT_COMMUNITY, + Name: cs.ExtCommunitySetName, + List: cs.ExtCommunityList, + } + sets = append(sets, ad) + } + for _, cs := range cd.BgpDefinedSets.LargeCommunitySets { + ad := &api.DefinedSet{ + Type: api.DefinedType_LARGE_COMMUNITY, + Name: cs.LargeCommunitySetName, + List: cs.LargeCommunityList, + } + sets = append(sets, ad) + } + for _, cs := range cd.BgpDefinedSets.AsPathSets { + ad := &api.DefinedSet{ + Type: api.DefinedType_AS_PATH, + Name: cs.AsPathSetName, + List: cs.AsPathList, + } + sets = append(sets, ad) + } + return sets, nil } -func (s *BgpServer) AddDefinedSet(a table.DefinedSet) error { +func (s *BgpServer) AddDefinedSet(ctx context.Context, r *api.AddDefinedSetRequest) error { return s.mgmtOperation(func() error { - return s.policy.AddDefinedSet(a) + if r == nil || r.Set == nil { + return fmt.Errorf("invalid request") + } + set, err := NewDefinedSetFromApiStruct(r.Set) + if err != nil { + return err + } + return s.policy.AddDefinedSet(set) }, false) } -func (s *BgpServer) DeleteDefinedSet(a table.DefinedSet, all bool) error { +func (s *BgpServer) DeleteDefinedSet(ctx context.Context, r *api.DeleteDefinedSetRequest) error { return s.mgmtOperation(func() error { - return s.policy.DeleteDefinedSet(a, all) + if r == nil || r.Set == nil { + return fmt.Errorf("invalid request") + } + set, err := NewDefinedSetFromApiStruct(r.Set) + if err != nil { + return err + } + return s.policy.DeleteDefinedSet(set, r.All) }, false) } -func (s *BgpServer) ReplaceDefinedSet(a table.DefinedSet) error { +func (s *BgpServer) ReplaceDefinedSet(ctx context.Context, r *api.ReplaceDefinedSetRequest) error { return s.mgmtOperation(func() error { - return s.policy.ReplaceDefinedSet(a) + if r == nil || r.Set == nil { + return fmt.Errorf("invalid request") + } + set, err := NewDefinedSetFromApiStruct(r.Set) + if err != nil { + return err + } + return s.policy.ReplaceDefinedSet(set) }, false) } @@ -2682,53 +3019,110 @@ func (s *BgpServer) GetStatement() (l []*config.Statement) { return l } -func (s *BgpServer) AddStatement(st *table.Statement) error { +func (s *BgpServer) ListStatement(ctx context.Context, r *api.ListStatementRequest) ([]*api.Statement, error) { + l := make([]*api.Statement, 0) + s.mgmtOperation(func() error { + for _, st := range s.policy.GetStatement() { + l = append(l, toStatementApi(st)) + } + return nil + }, false) + return l, nil +} + +func (s *BgpServer) AddStatement(ctx context.Context, r *api.AddStatementRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Statement == nil { + return fmt.Errorf("invalid request") + } + st, err := NewStatementFromApiStruct(r.Statement) + if err != nil { + return err + } return s.policy.AddStatement(st) }, false) } -func (s *BgpServer) DeleteStatement(st *table.Statement, all bool) error { +func (s *BgpServer) DeleteStatement(ctx context.Context, r *api.DeleteStatementRequest) error { return s.mgmtOperation(func() error { - return s.policy.DeleteStatement(st, all) + if r == nil || r.Statement == nil { + return fmt.Errorf("invalid request") + } + st, err := NewStatementFromApiStruct(r.Statement) + if err == nil { + err = s.policy.DeleteStatement(st, r.All) + } + return err }, false) } -func (s *BgpServer) ReplaceStatement(st *table.Statement) error { +func (s *BgpServer) ReplaceStatement(ctx context.Context, r *api.ReplaceStatementRequest) error { return s.mgmtOperation(func() error { - return s.policy.ReplaceStatement(st) + if r == nil || r.Statement == nil { + return fmt.Errorf("invalid request") + } + st, err := NewStatementFromApiStruct(r.Statement) + if err == nil { + err = s.policy.ReplaceStatement(st) + } + return err }, false) } -func (s *BgpServer) GetPolicy() (l []*config.PolicyDefinition) { +func (s *BgpServer) ListPolicy(ctx context.Context, r *api.ListPolicyRequest) ([]*api.Policy, error) { + l := make([]*api.Policy, 0) s.mgmtOperation(func() error { - l = s.policy.GetAllPolicy() + for _, p := range s.policy.GetAllPolicy() { + l = append(l, toPolicyApi(p)) + } return nil }, false) - return l + return l, nil } -func (s *BgpServer) AddPolicy(x *table.Policy, refer bool) error { +func (s *BgpServer) AddPolicy(ctx context.Context, r *api.AddPolicyRequest) error { return s.mgmtOperation(func() error { - return s.policy.AddPolicy(x, refer) + if r == nil || r.Policy == nil { + return fmt.Errorf("invalid request") + } + p, err := NewPolicyFromApiStruct(r.Policy) + if err == nil { + err = s.policy.AddPolicy(p, r.ReferExistingStatements) + } + return err }, false) } -func (s *BgpServer) DeletePolicy(x *table.Policy, all, preserve bool) error { +func (s *BgpServer) DeletePolicy(ctx context.Context, r *api.DeletePolicyRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Policy == nil { + return fmt.Errorf("invalid request") + } + p, err := NewPolicyFromApiStruct(r.Policy) + if err != nil { + return err + } + l := make([]string, 0, len(s.neighborMap)+1) for _, peer := range s.neighborMap { l = append(l, peer.ID()) } l = append(l, table.GLOBAL_RIB_NAME) - return s.policy.DeletePolicy(x, all, preserve, l) + return s.policy.DeletePolicy(p, r.All, r.PreserveStatements, l) }, false) } -func (s *BgpServer) ReplacePolicy(x *table.Policy, refer, preserve bool) error { +func (s *BgpServer) ReplacePolicy(ctx context.Context, r *api.ReplacePolicyRequest) error { return s.mgmtOperation(func() error { - return s.policy.ReplacePolicy(x, refer, preserve) + if r == nil || r.Policy == nil { + return fmt.Errorf("invalid request") + } + p, err := NewPolicyFromApiStruct(r.Policy) + if err == nil { + err = s.policy.ReplacePolicy(p, r.ReferExistingStatements, r.PreserveStatements) + } + return err }, false) } @@ -2751,111 +3145,197 @@ func (server *BgpServer) toPolicyInfo(name string, dir table.PolicyDirection) (s } } -func (s *BgpServer) GetPolicyAssignment(name string, dir table.PolicyDirection) (rt table.RouteType, l []*config.PolicyDefinition, err error) { - err = s.mgmtOperation(func() error { - var id string - id, err = s.toPolicyInfo(name, dir) +func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyAssignmentRequest) ([]*api.PolicyAssignment, error) { + a := make([]*api.PolicyAssignment, 0) + err := s.mgmtOperation(func() error { + if r == nil || r.Direction == api.PolicyDirection_UNKNOWN { + return fmt.Errorf("invalid request") + } + dir := func() table.PolicyDirection { + if r.Direction == api.PolicyDirection_EXPORT { + return table.POLICY_DIRECTION_EXPORT + } + return table.POLICY_DIRECTION_IMPORT + }() + + id, err := s.toPolicyInfo(r.Name, dir) if err != nil { - rt = table.ROUTE_TYPE_NONE return err } - rt, l, err = s.policy.GetPolicyAssignment(id, dir) - return nil + rt, l, err := s.policy.GetPolicyAssignment(id, dir) + if err != nil { + return err + } + + policies := make([]*table.Policy, 0, len(l)) + for _, p := range l { + t, err := table.NewPolicy(*p) + if err != nil { + return err + } + policies = append(policies, t) + } + t := &table.PolicyAssignment{ + Name: r.Name, + Type: dir, + Default: rt, + Policies: policies, + } + a = append(a, NewAPIPolicyAssignmentFromTableStruct(t)) + return err }, false) - return rt, l, err + return a, err } -func (s *BgpServer) AddPolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, def table.RouteType) error { +func (s *BgpServer) AddPolicyAssignment(ctx context.Context, r *api.AddPolicyAssignmentRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Assignment == nil { + return fmt.Errorf("invalid request") + } + name, dir, err := toPolicyAssignmentName(r.Assignment) + if err != nil { + return err + } + id, err := s.toPolicyInfo(name, dir) if err != nil { return err } - return s.policy.AddPolicyAssignment(id, dir, policies, def) + return s.policy.AddPolicyAssignment(id, dir, toPolicyDefinition(r.Assignment.Policies), defaultRouteType(r.Assignment.Default)) }, false) } -func (s *BgpServer) DeletePolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, all bool) error { +func (s *BgpServer) DeletePolicyAssignment(ctx context.Context, r *api.DeletePolicyAssignmentRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Assignment == nil { + return fmt.Errorf("invalid request") + } + name, dir, err := toPolicyAssignmentName(r.Assignment) + if err != nil { + return err + } + id, err := s.toPolicyInfo(name, dir) if err != nil { return err } - return s.policy.DeletePolicyAssignment(id, dir, policies, all) + return s.policy.DeletePolicyAssignment(id, dir, toPolicyDefinition(r.Assignment.Policies), r.All) }, false) } -func (s *BgpServer) ReplacePolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, def table.RouteType) error { +//func (s *BgpServer) ReplacePolicyAssignment(name string, dir table.PolicyDirection, policies []*config.PolicyDefinition, def table.RouteType) error { +func (s *BgpServer) ReplacePolicyAssignment(ctx context.Context, r *api.ReplacePolicyAssignmentRequest) error { return s.mgmtOperation(func() error { + if r == nil || r.Assignment == nil { + return fmt.Errorf("invalid request") + } + name, dir, err := toPolicyAssignmentName(r.Assignment) + if err != nil { + return err + } id, err := s.toPolicyInfo(name, dir) if err != nil { return err } - return s.policy.ReplacePolicyAssignment(id, dir, policies, def) + return s.policy.ReplacePolicyAssignment(id, dir, toPolicyDefinition(r.Assignment.Policies), defaultRouteType(r.Assignment.Default)) }, false) } -func (s *BgpServer) EnableMrt(c *config.MrtConfig) error { +func (s *BgpServer) EnableMrt(ctx context.Context, r *api.EnableMrtRequest) error { return s.mgmtOperation(func() error { - return s.mrtManager.enable(c) + return s.mrtManager.enable(&config.MrtConfig{ + RotationInterval: r.Interval, + DumpType: config.IntToMrtTypeMap[int(r.DumpType)], + FileName: r.Filename, + }) }, false) } -func (s *BgpServer) DisableMrt(c *config.MrtConfig) error { +func (s *BgpServer) DisableMrt(ctx context.Context, r *api.DisableMrtRequest) error { return s.mgmtOperation(func() error { - return s.mrtManager.disable(c) + return s.mrtManager.disable(&config.MrtConfig{}) }, false) } -func (s *BgpServer) GetRpki() (l []*config.RpkiServer, err error) { +func (s *BgpServer) ListRpki(ctx context.Context, r *api.ListRpkiRequest) (l []*api.Rpki, err error) { err = s.mgmtOperation(func() error { - l = s.roaManager.GetServers() + for _, r := range s.roaManager.GetServers() { + received := &r.State.RpkiMessages.RpkiReceived + sent := &r.State.RpkiMessages.RpkiSent + rpki := &api.Rpki{ + Conf: &api.RPKIConf{ + Address: r.Config.Address, + RemotePort: uint32(r.Config.Port), + }, + State: &api.RPKIState{ + Uptime: r.State.Uptime, + Downtime: r.State.Downtime, + Up: r.State.Up, + RecordIpv4: r.State.RecordsV4, + RecordIpv6: r.State.RecordsV6, + PrefixIpv4: r.State.PrefixesV4, + PrefixIpv6: r.State.PrefixesV6, + Serial: r.State.SerialNumber, + ReceivedIpv4: received.Ipv4Prefix, + ReceivedIpv6: received.Ipv6Prefix, + SerialNotify: received.SerialNotify, + CacheReset: received.CacheReset, + CacheResponse: received.CacheResponse, + EndOfData: received.EndOfData, + Error: received.Error, + SerialQuery: sent.SerialQuery, + ResetQuery: sent.ResetQuery, + }, + } + l = append(l, rpki) + } return nil }, false) return l, err } -func (s *BgpServer) GetRoa(family bgp.RouteFamily) (l []*table.ROA, err error) { +func (s *BgpServer) ListRpkiTable(ctx context.Context, r *api.ListRpkiTableRequest) (l []*api.Roa, err error) { s.mgmtOperation(func() error { - l, err = s.roaManager.GetRoa(family) + var roas []*table.ROA + roas, err = s.roaManager.GetRoa(bgp.RouteFamily(r.Family)) + if err == nil { + l = append(l, NewRoaListFromTableStructList(roas)...) + } return nil }, false) - return l, err -} - -func (s *BgpServer) AddRpki(c *config.RpkiServerConfig) error { - return s.mgmtOperation(func() error { - return s.roaManager.AddServer(net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port))), c.RecordLifetime) - }, false) + return } -func (s *BgpServer) DeleteRpki(c *config.RpkiServerConfig) error { +func (s *BgpServer) AddRpki(ctx context.Context, r *api.AddRpkiRequest) error { return s.mgmtOperation(func() error { - return s.roaManager.DeleteServer(c.Address) + return s.roaManager.AddServer(net.JoinHostPort(r.Address, strconv.Itoa(int(r.Port))), r.Lifetime) }, false) } -func (s *BgpServer) EnableRpki(c *config.RpkiServerConfig) error { +func (s *BgpServer) DeleteRpki(ctx context.Context, r *api.DeleteRpkiRequest) error { return s.mgmtOperation(func() error { - return s.roaManager.Enable(c.Address) + return s.roaManager.DeleteServer(r.Address) }, false) } -func (s *BgpServer) DisableRpki(c *config.RpkiServerConfig) error { +func (s *BgpServer) EnableRpki(ctx context.Context, r *api.EnableRpkiRequest) error { return s.mgmtOperation(func() error { - return s.roaManager.Disable(c.Address) + return s.roaManager.Enable(r.Address) }, false) } -func (s *BgpServer) ResetRpki(c *config.RpkiServerConfig) error { +func (s *BgpServer) DisableRpki(ctx context.Context, r *api.DisableRpkiRequest) error { return s.mgmtOperation(func() error { - return s.roaManager.Reset(c.Address) + return s.roaManager.Disable(r.Address) }, false) } -func (s *BgpServer) SoftResetRpki(c *config.RpkiServerConfig) error { +func (s *BgpServer) ResetRpki(ctx context.Context, r *api.ResetRpkiRequest) error { return s.mgmtOperation(func() error { - return s.roaManager.SoftReset(c.Address) + if r.Soft { + return s.roaManager.SoftReset(r.Address) + } + return s.roaManager.Reset(r.Address) }, false) } @@ -3054,7 +3534,7 @@ func (w *Watcher) Generate(t WatchEventType) error { }() l := make([]*config.Neighbor, 0, len(w.s.neighborMap)) for _, peer := range w.s.neighborMap { - l = append(l, w.s.ToConfig(peer, false)) + l = append(l, w.s.toConfig(peer, false)) } w.notify(&WatchEventTable{PathList: pathList, Neighbor: l}) default: @@ -3158,7 +3638,7 @@ func (s *BgpServer) Watch(opts ...WatchOption) (w *Watcher) { if notEstablished { continue } - configNeighbor := w.s.ToConfig(peer, false) + configNeighbor := w.s.toConfig(peer, false) for _, rf := range peer.configuredRFlist() { peer.fsm.lock.RLock() _, y := peer.fsm.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER] @@ -3213,7 +3693,7 @@ func (s *BgpServer) Watch(opts ...WatchOption) (w *Watcher) { // create copy which can be access to without mutex var configNeighbor *config.Neighbor if peer, ok := s.neighborMap[peerInfo.Address.String()]; ok { - configNeighbor = w.s.ToConfig(peer, false) + configNeighbor = w.s.toConfig(peer, false) } w.notify(&WatchEventUpdate{ diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index e4a5e677..a7142079 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/internal/pkg/config" "github.com/osrg/gobgp/internal/pkg/table" "github.com/osrg/gobgp/pkg/packet/bgp" @@ -35,50 +36,68 @@ func TestModPolicyAssign(t *testing.T) { assert := assert.New(t) s := NewBgpServer() go s.Serve() - err := s.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: -1, + err := s.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 1, + RouterId: "1.1.1.1", + ListenPort: -1, }, }) assert.Nil(err) - defer s.Stop() + defer s.StopBgp(context.Background(), &api.StopBgpRequest{}) - err = s.AddPolicy(&table.Policy{Name: "p1"}, false) + err = s.AddPolicy(context.Background(), &api.AddPolicyRequest{Policy: NewAPIPolicyFromTableStruct(&table.Policy{Name: "p1"})}) assert.Nil(err) - err = s.AddPolicy(&table.Policy{Name: "p2"}, false) + err = s.AddPolicy(context.Background(), &api.AddPolicyRequest{Policy: NewAPIPolicyFromTableStruct(&table.Policy{Name: "p2"})}) assert.Nil(err) - err = s.AddPolicy(&table.Policy{Name: "p3"}, false) + err = s.AddPolicy(context.Background(), &api.AddPolicyRequest{Policy: NewAPIPolicyFromTableStruct(&table.Policy{Name: "p3"})}) assert.Nil(err) - err = s.AddPolicyAssignment("", table.POLICY_DIRECTION_IMPORT, - []*config.PolicyDefinition{&config.PolicyDefinition{Name: "p1"}, &config.PolicyDefinition{Name: "p2"}, &config.PolicyDefinition{Name: "p3"}}, table.ROUTE_TYPE_ACCEPT) + f := func(l []*config.PolicyDefinition) *api.PolicyAssignment { + pl := make([]*api.Policy, 0, len(l)) + for _, d := range l { + pl = append(pl, toPolicyApi(d)) + } + return &api.PolicyAssignment{ + Policies: pl, + } + } + + r := f([]*config.PolicyDefinition{&config.PolicyDefinition{Name: "p1"}, &config.PolicyDefinition{Name: "p2"}, &config.PolicyDefinition{Name: "p3"}}) + r.Type = api.PolicyDirection_IMPORT + r.Default = api.RouteAction_ACCEPT + err = s.AddPolicyAssignment(context.Background(), &api.AddPolicyAssignmentRequest{Assignment: r}) assert.Nil(err) - err = s.DeletePolicyAssignment("", table.POLICY_DIRECTION_IMPORT, - []*config.PolicyDefinition{&config.PolicyDefinition{Name: "p1"}}, false) + ps, err := s.ListPolicyAssignment(context.Background(), &api.ListPolicyAssignmentRequest{Direction: api.PolicyDirection_IMPORT}) assert.Nil(err) + assert.Equal(len(ps[0].Policies), 3) - _, ps, _ := s.GetPolicyAssignment("", table.POLICY_DIRECTION_IMPORT) - assert.Equal(len(ps), 2) + r = f([]*config.PolicyDefinition{&config.PolicyDefinition{Name: "p1"}}) + r.Type = api.PolicyDirection_IMPORT + r.Default = api.RouteAction_ACCEPT + err = s.DeletePolicyAssignment(context.Background(), &api.DeletePolicyAssignmentRequest{Assignment: r}) + assert.Nil(err) + + ps, _ = s.ListPolicyAssignment(context.Background(), &api.ListPolicyAssignmentRequest{Direction: api.PolicyDirection_IMPORT}) + assert.Equal(len(ps[0].Policies), 2) } func TestMonitor(test *testing.T) { assert := assert.New(test) s := NewBgpServer() go s.Serve() - err := s.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, + err := s.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 1, + RouterId: "1.1.1.1", + ListenPort: 10179, }, }) assert.Nil(err) - defer s.Stop() + defer s.StopBgp(context.Background(), &api.StopBgpRequest{}) n := &config.Neighbor{ Config: config.NeighborConfig{ @@ -91,20 +110,20 @@ func TestMonitor(test *testing.T) { }, }, } - err = s.AddNeighbor(n) + err = s.addNeighbor(n) assert.Nil(err) t := NewBgpServer() go t.Serve() - err = t.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, + err = t.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 2, + RouterId: "2.2.2.2", + ListenPort: -1, }, }) assert.Nil(err) - defer t.Stop() + defer t.StopBgp(context.Background(), &api.StopBgpRequest{}) m := &config.Neighbor{ Config: config.NeighborConfig{ @@ -117,12 +136,12 @@ func TestMonitor(test *testing.T) { }, }, } - err = t.AddNeighbor(m) + err = t.AddPeer(context.Background(), &api.AddPeerRequest{Peer: NewPeerFromConfigStruct(m)}) assert.Nil(err) for { time.Sleep(time.Second) - if t.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { + if t.getNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { break } } @@ -135,7 +154,7 @@ func TestMonitor(test *testing.T) { bgp.NewPathAttributeOrigin(0), bgp.NewPathAttributeNextHop("10.0.0.1"), } - if _, err := t.AddPath("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.0.0.0"), false, attrs, time.Now(), false)}); err != nil { + if err := t.addPathList("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.0.0.0"), false, attrs, time.Now(), false)}); err != nil { log.Fatal(err) } ev := <-w.Event() @@ -146,7 +165,7 @@ func TestMonitor(test *testing.T) { // Withdraws the previous route. // NOTE: Withdow should not require any path attribute. - if _, err := t.AddPath("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.0.0.0"), true, nil, time.Now(), false)}); err != nil { + if err := t.addPathList("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.0.0.0"), true, nil, time.Now(), false)}); err != nil { log.Fatal(err) } ev = <-w.Event() @@ -159,12 +178,12 @@ func TestMonitor(test *testing.T) { w.Stop() // Prepares an initial route to test WatchUpdate with "current" flag. - if _, err := t.AddPath("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.1.0.0"), false, attrs, time.Now(), false)}); err != nil { + if err := t.addPathList("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.1.0.0"), false, attrs, time.Now(), false)}); err != nil { log.Fatal(err) } for { // Waits for the initial route will be advertised. - rib, _, err := s.GetRib("", bgp.RF_IPv4_UC, nil) + rib, _, err := s.getRib("", bgp.RF_IPv4_UC, nil) if err != nil { log.Fatal(err) } @@ -188,7 +207,7 @@ func TestMonitor(test *testing.T) { assert.Equal(len(u.PathList), 0) // End of RIB // Advertises an additional route. - if _, err := t.AddPath("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.2.0.0"), false, attrs, time.Now(), false)}); err != nil { + if err := t.addPathList("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.2.0.0"), false, attrs, time.Now(), false)}); err != nil { log.Fatal(err) } ev = <-w.Event() @@ -199,7 +218,7 @@ func TestMonitor(test *testing.T) { // Withdraws the previous route. // NOTE: Withdow should not require any path attribute. - if _, err := t.AddPath("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.2.0.0"), true, nil, time.Now(), false)}); err != nil { + if err := t.addPathList("", []*table.Path{table.NewPath(nil, bgp.NewIPAddrPrefix(24, "10.2.0.0"), true, nil, time.Now(), false)}); err != nil { log.Fatal(err) } ev = <-w.Event() @@ -216,36 +235,35 @@ func TestNumGoroutineWithAddDeleteNeighbor(t *testing.T) { assert := assert.New(t) s := NewBgpServer() go s.Serve() - err := s.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: -1, + err := s.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 1, + RouterId: "1.1.1.1", + ListenPort: -1, }, }) assert.Nil(err) - defer s.Stop() + defer s.StopBgp(context.Background(), &api.StopBgpRequest{}) // wait a few seconds to avoid taking effect from other test cases. time.Sleep(time.Second * 5) num := runtime.NumGoroutine() - n := &config.Neighbor{ - Config: config.NeighborConfig{ + p := &api.Peer{ + Conf: &api.PeerConf{ NeighborAddress: "127.0.0.1", PeerAs: 2, }, - Transport: config.Transport{ - Config: config.TransportConfig{ - PassiveMode: true, - }, + Transport: &api.Transport{ + PassiveMode: true, }, } - err = s.AddNeighbor(n) + + err = s.AddPeer(context.Background(), &api.AddPeerRequest{Peer: p}) assert.Nil(err) - err = s.DeleteNeighbor(n) + err = s.DeletePeer(context.Background(), &api.DeletePeerRequest{Address: "127.0.0.1"}) assert.Nil(err) // wait goroutines to finish (e.g. internal goroutine for // InfiniteChannel) @@ -419,15 +437,15 @@ func TestPeerGroup(test *testing.T) { log.SetLevel(log.DebugLevel) s := NewBgpServer() go s.Serve() - err := s.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, + err := s.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 1, + RouterId: "1.1.1.1", + ListenPort: 10179, }, }) assert.Nil(err) - defer s.Stop() + defer s.StopBgp(context.Background(), &api.StopBgpRequest{}) g := &config.PeerGroup{ Config: config.PeerGroupConfig{ @@ -435,7 +453,7 @@ func TestPeerGroup(test *testing.T) { PeerGroupName: "g", }, } - err = s.AddPeerGroup(g) + err = s.addPeerGroup(g) assert.Nil(err) n := &config.Neighbor{ @@ -461,20 +479,20 @@ func TestPeerGroup(test *testing.T) { }, } config.RegisterConfiguredFields("127.0.0.1", configured) - err = s.AddNeighbor(n) + err = s.AddPeer(context.Background(), &api.AddPeerRequest{Peer: NewPeerFromConfigStruct(n)}) assert.Nil(err) t := NewBgpServer() go t.Serve() - err = t.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, + err = t.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 2, + RouterId: "2.2.2.2", + ListenPort: -1, }, }) assert.Nil(err) - defer t.Stop() + defer t.StopBgp(context.Background(), &api.StopBgpRequest{}) m := &config.Neighbor{ Config: config.NeighborConfig{ @@ -487,12 +505,12 @@ func TestPeerGroup(test *testing.T) { }, }, } - err = t.AddNeighbor(m) + err = t.AddPeer(context.Background(), &api.AddPeerRequest{Peer: NewPeerFromConfigStruct(m)}) assert.Nil(err) for { time.Sleep(time.Second) - if t.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { + if t.getNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { break } } @@ -503,15 +521,15 @@ func TestDynamicNeighbor(t *testing.T) { log.SetLevel(log.DebugLevel) s1 := NewBgpServer() go s1.Serve() - err := s1.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, + err := s1.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 1, + RouterId: "1.1.1.1", + ListenPort: 10179, }, }) assert.Nil(err) - defer s1.Stop() + defer s1.StopBgp(context.Background(), &api.StopBgpRequest{}) g := &config.PeerGroup{ Config: config.PeerGroupConfig{ @@ -519,29 +537,29 @@ func TestDynamicNeighbor(t *testing.T) { PeerGroupName: "g", }, } - err = s1.AddPeerGroup(g) + err = s1.addPeerGroup(g) assert.Nil(err) - d := &config.DynamicNeighbor{ - Config: config.DynamicNeighborConfig{ + d := &api.AddDynamicNeighborRequest{ + DynamicNeighbor: &api.DynamicNeighbor{ Prefix: "127.0.0.0/24", PeerGroup: "g", }, } - err = s1.AddDynamicNeighbor(d) + err = s1.AddDynamicNeighbor(context.Background(), d) assert.Nil(err) s2 := NewBgpServer() go s2.Serve() - err = s2.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, + err = s2.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 2, + RouterId: "2.2.2.2", + ListenPort: -1, }, }) assert.Nil(err) - defer s2.Stop() + defer s2.StopBgp(context.Background(), &api.StopBgpRequest{}) m := &config.Neighbor{ Config: config.NeighborConfig{ @@ -554,13 +572,13 @@ func TestDynamicNeighbor(t *testing.T) { }, }, } - err = s2.AddNeighbor(m) + err = s2.AddPeer(context.Background(), &api.AddPeerRequest{Peer: NewPeerFromConfigStruct(m)}) assert.Nil(err) for { time.Sleep(time.Second) - if s2.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { + if s2.getNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { break } } @@ -570,15 +588,15 @@ func TestGracefulRestartTimerExpired(t *testing.T) { assert := assert.New(t) s1 := NewBgpServer() go s1.Serve() - err := s1.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, + err := s1.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 1, + RouterId: "1.1.1.1", + ListenPort: 10179, }, }) assert.Nil(err) - defer s1.Stop() + defer s1.StopBgp(context.Background(), &api.StopBgpRequest{}) n := &config.Neighbor{ Config: config.NeighborConfig{ @@ -597,20 +615,20 @@ func TestGracefulRestartTimerExpired(t *testing.T) { }, }, } - err = s1.AddNeighbor(n) + err = s1.addNeighbor(n) assert.Nil(err) s2 := NewBgpServer() go s2.Serve() - err = s2.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, + err = s2.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 2, + RouterId: "2.2.2.2", + ListenPort: -1, }, }) require.NoError(t, err) - defer s2.Stop() + defer s2.StopBgp(context.Background(), &api.StopBgpRequest{}) m := &config.Neighbor{ Config: config.NeighborConfig{ @@ -629,13 +647,13 @@ func TestGracefulRestartTimerExpired(t *testing.T) { }, }, } - err = s2.AddNeighbor(m) + err = s2.addNeighbor(m) assert.Nil(err) // Waiting for BGP session established. for { time.Sleep(time.Second) - if s2.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { + if s2.getNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { break } } @@ -645,7 +663,7 @@ func TestGracefulRestartTimerExpired(t *testing.T) { for _, n := range s2.neighborMap { n.fsm.conn.Close() } - s2.Stop() + s2.StopBgp(context.Background(), &api.StopBgpRequest{}) time.Sleep(5 * time.Second) @@ -663,7 +681,7 @@ func TestGracefulRestartTimerExpired(t *testing.T) { // Waiting for Graceful Restart timer expired and moving on to IDLE state. for { - if s1.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_IDLE { + if s1.getNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_IDLE { break } diff --git a/pkg/server/zclient.go b/pkg/server/zclient.go index 3ef057ce..1ee1eee7 100644 --- a/pkg/server/zclient.go +++ b/pkg/server/zclient.go @@ -297,7 +297,7 @@ func (z *zebraClient) getPathListWithNexthopUpdate(body *zebra.NexthopUpdateBody } for _, rf := range rfList { - tbl, _, err := z.server.GetRib("", rf, nil) + tbl, _, err := z.server.getRib("", rf, nil) if err != nil { log.WithFields(log.Fields{ "Topic": "Zebra", @@ -315,7 +315,7 @@ func (z *zebraClient) getPathListWithNexthopUpdate(body *zebra.NexthopUpdateBody func (z *zebraClient) updatePathByNexthopCache(paths []*table.Path) { paths = z.nexthopCache.applyToPathList(paths) if len(paths) > 0 { - if err := z.server.UpdatePath("", paths); err != nil { + if err := z.server.updatePath("", paths); err != nil { log.WithFields(log.Fields{ "Topic": "Zebra", "PathList": paths, @@ -339,7 +339,7 @@ func (z *zebraClient) loop() { switch body := msg.Body.(type) { case *zebra.IPRouteBody: if path := newPathFromIPRouteMessage(msg); path != nil { - if _, err := z.server.AddPath("", []*table.Path{path}); err != nil { + if err := z.server.addPathList("", []*table.Path{path}); err != nil { log.WithFields(log.Fields{ "Topic": "Zebra", "Path": path, @@ -395,7 +395,7 @@ func (z *zebraClient) loop() { case *WatchEventUpdate: if body := newNexthopRegisterBody(msg.PathList, z.nexthopCache); body != nil { vrfID := uint16(0) - for _, vrf := range z.server.GetVrf() { + for _, vrf := range z.server.listVrf() { if vrf.Name == msg.Neighbor.Config.Vrf { vrfID = uint16(vrf.Id) } |