diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-07-29 00:43:52 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-07-29 00:43:52 +0900 |
commit | af98780240d247f4df352c364002d1d77e71f31e (patch) | |
tree | 96328d3ea91123062588447ac2b0557495e692fa /server | |
parent | 2a552a49b4991fcf765dbbbbd56619256dab96ac (diff) |
move grpc_server.go from server/ to api/
Now all gRPC code was moved to api/.
server/ isn't dependent on gRPC anymore.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'server')
-rw-r--r-- | server/grpc_server.go | 1673 |
1 files changed, 0 insertions, 1673 deletions
diff --git a/server/grpc_server.go b/server/grpc_server.go deleted file mode 100644 index 03dc9c7b..00000000 --- a/server/grpc_server.go +++ /dev/null @@ -1,1673 +0,0 @@ -// Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package server - -import ( - "fmt" - log "github.com/Sirupsen/logrus" - api "github.com/osrg/gobgp/api" - "github.com/osrg/gobgp/config" - "github.com/osrg/gobgp/packet/bgp" - "github.com/osrg/gobgp/table" - "golang.org/x/net/context" - "google.golang.org/grpc" - "io" - "net" - "reflect" - "regexp" - "strconv" - "strings" - "sync" - "time" -) - -type Server struct { - bgpServer *BgpServer - grpcServer *grpc.Server - hosts string -} - -func NewGrpcServer(b *BgpServer, hosts string) *Server { - grpc.EnableTracing = false - grpcServer := grpc.NewServer() - server := &Server{ - bgpServer: b, - grpcServer: grpcServer, - hosts: hosts, - } - api.RegisterGobgpApiServer(grpcServer, server) - return server -} - -func (s *Server) Serve() error { - var wg sync.WaitGroup - l := strings.Split(s.hosts, ",") - wg.Add(len(l)) - - serve := func(host string) { - for { - defer wg.Done() - lis, err := net.Listen("tcp", fmt.Sprintf(host)) - if err != nil { - log.WithFields(log.Fields{ - "Topic": "grpc", - "Key": host, - "Error": err, - }).Warn("listen failed") - return - } - err = s.grpcServer.Serve(lis) - log.WithFields(log.Fields{ - "Topic": "grpc", - "Key": host, - "Error": err, - }).Warn("accept failed") - } - } - for _, host := range l { - go serve(host) - } - wg.Wait() - return nil -} - -func (s *Server) GetNeighbor(ctx context.Context, arg *api.GetNeighborRequest) (*api.GetNeighborResponse, error) { - toApi := func(pconf *config.Neighbor) *api.Peer { - prefixLimits := make([]*api.PrefixLimit, 0, len(pconf.AfiSafis)) - for _, family := range pconf.AfiSafis { - if c := family.PrefixLimit.Config; c.MaxPrefixes > 0 { - k, _ := bgp.GetRouteFamily(string(family.Config.AfiSafiName)) - prefixLimits = append(prefixLimits, &api.PrefixLimit{ - Family: uint32(k), - MaxPrefixes: c.MaxPrefixes, - ShutdownThresholdPct: uint32(c.ShutdownThresholdPct), - }) - } - } - - timer := pconf.Timers - s := pconf.State - return &api.Peer{ - Conf: &api.PeerConf{ - NeighborAddress: pconf.Config.NeighborAddress, - Id: s.Description, - PeerAs: pconf.Config.PeerAs, - LocalAs: pconf.Config.LocalAs, - PeerType: uint32(pconf.Config.PeerType.ToInt()), - AuthPassword: pconf.Config.AuthPassword, - RemovePrivateAs: uint32(pconf.Config.RemovePrivateAs.ToInt()), - RouteFlapDamping: pconf.Config.RouteFlapDamping, - SendCommunity: uint32(pconf.Config.SendCommunity.ToInt()), - Description: pconf.Config.Description, - PeerGroup: pconf.Config.PeerGroup, - RemoteCap: s.Capabilities.RemoteList, - LocalCap: s.Capabilities.LocalList, - PrefixLimits: prefixLimits, - }, - Info: &api.PeerState{ - BgpState: bgp.FSMState(s.SessionState.ToInt()).String(), - AdminState: s.AdminState, - Messages: &api.Messages{ - Received: &api.Message{ - NOTIFICATION: s.Messages.Received.Notification, - UPDATE: s.Messages.Received.Update, - OPEN: s.Messages.Received.Open, - KEEPALIVE: s.Messages.Received.Keepalive, - REFRESH: s.Messages.Received.Refresh, - DISCARDED: s.Messages.Received.Discarded, - TOTAL: s.Messages.Received.Total, - }, - Sent: &api.Message{ - NOTIFICATION: s.Messages.Sent.Notification, - UPDATE: s.Messages.Sent.Update, - OPEN: s.Messages.Sent.Open, - KEEPALIVE: s.Messages.Sent.Keepalive, - REFRESH: s.Messages.Sent.Refresh, - DISCARDED: s.Messages.Sent.Discarded, - TOTAL: s.Messages.Sent.Total, - }, - }, - Received: s.AdjTable.Received, - Accepted: s.AdjTable.Accepted, - Advertised: s.AdjTable.Advertised, - }, - Timers: &api.Timers{ - Config: &api.TimersConfig{ - ConnectRetry: uint64(timer.Config.ConnectRetry), - HoldTime: uint64(timer.Config.HoldTime), - KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), - }, - State: &api.TimersState{ - KeepaliveInterval: uint64(timer.State.KeepaliveInterval), - NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), - Uptime: uint64(timer.State.Uptime), - Downtime: uint64(timer.State.Downtime), - }, - }, - RouteReflector: &api.RouteReflector{ - RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, - RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId), - }, - RouteServer: &api.RouteServer{ - RouteServerClient: pconf.RouteServer.Config.RouteServerClient, - }, - } - } - - p := []*api.Peer{} - for _, e := range s.bgpServer.GetNeighbor() { - p = append(p, toApi(e)) - } - return &api.GetNeighborResponse{Peers: p}, nil -} - -func toPathApi(id string, path *table.Path) *api.Path { - nlri := path.GetNlri() - n, _ := nlri.Serialize() - family := uint32(bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI())) - pattrs := func(arg []bgp.PathAttributeInterface) [][]byte { - ret := make([][]byte, 0, len(arg)) - for _, a := range arg { - aa, _ := a.Serialize() - ret = append(ret, aa) - } - return ret - }(path.GetPathAttrs()) - return &api.Path{ - Nlri: n, - Pattrs: pattrs, - Age: path.GetTimestamp().Unix(), - IsWithdraw: path.IsWithdraw, - Validation: int32(path.Validation().ToInt()), - Filtered: path.Filtered(id) == table.POLICY_DIRECTION_IN, - Family: family, - SourceAsn: path.GetSource().AS, - SourceId: path.GetSource().ID.String(), - NeighborIp: path.GetSource().Address.String(), - Stale: path.IsStale(), - IsFromExternal: path.IsFromExternal(), - } -} - -func (s *Server) GetRib(ctx context.Context, arg *api.GetRibRequest) (*api.GetRibResponse, error) { - f := func() []*LookupPrefix { - l := make([]*LookupPrefix, 0, len(arg.Table.Destinations)) - for _, p := range arg.Table.Destinations { - l = append(l, &LookupPrefix{ - Prefix: p.Prefix, - LookupOption: func() LookupOption { - if p.LongerPrefixes { - return LOOKUP_LONGER - } else if p.ShorterPrefixes { - return LOOKUP_SHORTER - } - return LOOKUP_EXACT - }(), - }) - } - return l - } - - var in bool - var err error - var id string - var r map[string][]*table.Path - - family := bgp.RouteFamily(arg.Table.Family) - switch arg.Table.Type { - case api.Resource_LOCAL, api.Resource_GLOBAL: - id, r, err = s.bgpServer.GetRib(arg.Table.Name, family, f()) - case api.Resource_ADJ_IN: - in = true - fallthrough - case api.Resource_ADJ_OUT: - id, r, err = s.bgpServer.GetAdjRib(arg.Table.Name, family, in, f()) - case api.Resource_VRF: - id, r, err = s.bgpServer.GetVrfRib(arg.Table.Name, family, []*LookupPrefix{}) - default: - return nil, fmt.Errorf("unsupported resource type: %v", arg.Table.Type) - } - - dsts := make([]*api.Destination, 0, len(r)) - if err == nil { - for k, v := range r { - dsts = append(dsts, &api.Destination{ - Prefix: k, - Paths: func(paths []*table.Path) []*api.Path { - l := make([]*api.Path, 0, len(v)) - for i, p := range paths { - pp := toPathApi(id, p) - switch arg.Table.Type { - case api.Resource_LOCAL, api.Resource_GLOBAL: - if i == 0 { - pp.Best = true - } - } - l = append(l, pp) - } - return l - }(v), - }) - } - } - return &api.GetRibResponse{Table: &api.Table{ - Type: arg.Table.Type, - Family: arg.Table.Family, - Destinations: dsts}, - }, err -} - -func (s *Server) MonitorRib(arg *api.Table, stream api.GobgpApi_MonitorRibServer) error { - w, err := func() (*Watcher, error) { - switch arg.Type { - case api.Resource_GLOBAL: - return s.bgpServer.Watch(WatchBestPath()), nil - case api.Resource_ADJ_IN: - if arg.PostPolicy { - return s.bgpServer.Watch(WatchPostUpdate(false)), nil - } - return s.bgpServer.Watch(WatchUpdate(false)), nil - default: - return nil, fmt.Errorf("unsupported resource type: %v", arg.Type) - } - }() - if err != nil { - return nil - } - - return func() error { - defer func() { w.Stop() }() - - sendPath := func(pathList []*table.Path) error { - dsts := make(map[string]*api.Destination) - for _, path := range pathList { - if path == nil { - continue - } - if dst, y := dsts[path.GetNlri().String()]; y { - dst.Paths = append(dst.Paths, toPathApi(table.GLOBAL_RIB_NAME, path)) - } else { - dsts[path.GetNlri().String()] = &api.Destination{ - Prefix: path.GetNlri().String(), - Paths: []*api.Path{toPathApi(table.GLOBAL_RIB_NAME, path)}, - } - } - } - for _, dst := range dsts { - if err := stream.Send(dst); err != nil { - return err - } - } - return nil - } - for { - select { - case ev := <-w.Event(): - switch msg := ev.(type) { - case *WatchEventBestPath: - if err := sendPath(func() []*table.Path { - if len(msg.MultiPathList) > 0 { - l := make([]*table.Path, 0) - for _, p := range msg.MultiPathList { - l = append(l, p...) - } - return l - } else { - return msg.PathList - } - }()); err != nil { - return err - } - case *WatchEventUpdate: - if err := sendPath(msg.PathList); err != nil { - return err - } - } - } - } - }() -} - -func (s *Server) MonitorPeerState(arg *api.Arguments, stream api.GobgpApi_MonitorPeerStateServer) error { - return func() error { - w := s.bgpServer.Watch(WatchPeerState(false)) - defer func() { w.Stop() }() - - for { - select { - case ev := <-w.Event(): - switch msg := ev.(type) { - case *WatchEventPeerState: - if len(arg.Name) > 0 && arg.Name != msg.PeerAddress.String() { - continue - } - if err := stream.Send(&api.Peer{ - Conf: &api.PeerConf{ - PeerAs: msg.PeerAS, - LocalAs: msg.LocalAS, - NeighborAddress: msg.PeerAddress.String(), - Id: msg.PeerID.String(), - }, - Info: &api.PeerState{ - PeerAs: msg.PeerAS, - LocalAs: msg.LocalAS, - NeighborAddress: msg.PeerAddress.String(), - BgpState: msg.State.String(), - AdminState: msg.AdminState.String(), - }, - Transport: &api.Transport{ - LocalAddress: msg.LocalAddress.String(), - LocalPort: uint32(msg.LocalPort), - RemotePort: uint32(msg.PeerPort), - }, - }); err != nil { - return err - } - } - } - } - }() -} - -func (s *Server) ResetNeighbor(ctx context.Context, arg *api.ResetNeighborRequest) (*api.ResetNeighborResponse, error) { - return &api.ResetNeighborResponse{}, s.bgpServer.ResetNeighbor(arg.Address) -} - -func (s *Server) SoftResetNeighbor(ctx context.Context, arg *api.SoftResetNeighborRequest) (*api.SoftResetNeighborResponse, error) { - var err error - addr := arg.Address - if addr == "all" { - addr = "" - } - family := bgp.RouteFamily(0) - switch arg.Direction { - case api.SoftResetNeighborRequest_IN: - err = s.bgpServer.SoftResetIn(addr, family) - case api.SoftResetNeighborRequest_OUT: - err = s.bgpServer.SoftResetOut(addr, family) - default: - err = s.bgpServer.SoftReset(addr, family) - } - return &api.SoftResetNeighborResponse{}, err -} - -func (s *Server) ShutdownNeighbor(ctx context.Context, arg *api.ShutdownNeighborRequest) (*api.ShutdownNeighborResponse, error) { - return &api.ShutdownNeighborResponse{}, s.bgpServer.ShutdownNeighbor(arg.Address) -} - -func (s *Server) EnableNeighbor(ctx context.Context, arg *api.EnableNeighborRequest) (*api.EnableNeighborResponse, error) { - return &api.EnableNeighborResponse{}, s.bgpServer.EnableNeighbor(arg.Address) -} - -func (s *Server) DisableNeighbor(ctx context.Context, arg *api.DisableNeighborRequest) (*api.DisableNeighborResponse, error) { - return &api.DisableNeighborResponse{}, s.bgpServer.DisableNeighbor(arg.Address) -} - -func (s *Server) api2PathList(resource api.Resource, ApiPathList []*api.Path) ([]*table.Path, error) { - var nlri bgp.AddrPrefixInterface - var nexthop string - var pi *table.PeerInfo - - pathList := make([]*table.Path, 0, len(ApiPathList)) - for _, path := range ApiPathList { - seen := make(map[bgp.BGPAttrType]bool) - - pattr := make([]bgp.PathAttributeInterface, 0) - extcomms := make([]bgp.ExtendedCommunityInterface, 0) - - if path.SourceAsn != 0 { - pi = &table.PeerInfo{ - AS: path.SourceAsn, - LocalID: net.ParseIP(path.SourceId), - } - } - - if len(path.Nlri) > 0 { - nlri = &bgp.IPAddrPrefix{} - err := nlri.DecodeFromBytes(path.Nlri) - if err != nil { - return nil, err - } - } - - for _, attr := range path.Pattrs { - p, err := bgp.GetPathAttribute(attr) - if err != nil { - return nil, err - } - - err = p.DecodeFromBytes(attr) - if err != nil { - return nil, err - } - - if _, ok := seen[p.GetType()]; !ok { - seen[p.GetType()] = true - } else { - return nil, fmt.Errorf("the path attribute apears twice. Type : " + strconv.Itoa(int(p.GetType()))) - } - switch p.GetType() { - case bgp.BGP_ATTR_TYPE_NEXT_HOP: - nexthop = p.(*bgp.PathAttributeNextHop).Value.String() - case bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES: - value := p.(*bgp.PathAttributeExtendedCommunities).Value - if len(value) > 0 { - extcomms = append(extcomms, value...) - } - case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI: - mpreach := p.(*bgp.PathAttributeMpReachNLRI) - if len(mpreach.Value) != 1 { - return nil, fmt.Errorf("include only one route in mp_reach_nlri") - } - nlri = mpreach.Value[0] - nexthop = mpreach.Nexthop.String() - default: - pattr = append(pattr, p) - } - } - - if nlri == nil || nexthop == "" { - return nil, fmt.Errorf("not found nlri or nexthop") - } - - rf := bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()) - - if resource != api.Resource_VRF && rf == bgp.RF_IPv4_UC { - pattr = append(pattr, bgp.NewPathAttributeNextHop(nexthop)) - } else { - pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) - } - - if len(extcomms) > 0 { - pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms)) - } - newPath := table.NewPath(pi, nlri, path.IsWithdraw, pattr, time.Now(), path.NoImplicitWithdraw) - newPath.SetIsFromExternal(path.IsFromExternal) - pathList = append(pathList, newPath) - } - 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) DeletePath(ctx context.Context, arg *api.DeletePathRequest) (*api.DeletePathResponse, 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 &api.DeletePathResponse{}, s.bgpServer.DeletePath(arg.Uuid, bgp.RouteFamily(arg.Family), arg.VrfId, pathList) -} - -func (s *Server) EnableMrt(ctx context.Context, arg *api.EnableMrtRequest) (*api.EnableMrtResponse, error) { - return &api.EnableMrtResponse{}, s.bgpServer.EnableMrt(&config.Mrt{ - Interval: arg.Interval, - DumpType: config.IntToMrtTypeMap[int(arg.DumpType)], - FileName: arg.Filename, - }) -} - -func (s *Server) DisableMrt(ctx context.Context, arg *api.DisableMrtRequest) (*api.DisableMrtResponse, error) { - return &api.DisableMrtResponse{}, s.bgpServer.DisableMrt() -} - -func (s *Server) InjectMrt(stream api.GobgpApi_InjectMrtServer) error { - for { - arg, err := stream.Recv() - - if err == io.EOF { - break - } else if err != nil { - return err - } - - 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 { - return err - } else { - if _, err = s.bgpServer.AddPath("", pathList); err != nil { - return err - } - } - } - return stream.SendAndClose(&api.InjectMrtResponse{}) -} - -func (s *Server) AddBmp(ctx context.Context, arg *api.AddBmpRequest) (*api.AddBmpResponse, error) { - return &api.AddBmpResponse{}, s.bgpServer.AddBmp(&config.BmpServerConfig{ - Address: arg.Address, - Port: arg.Port, - RouteMonitoringPolicy: config.BmpRouteMonitoringPolicyType(arg.Type), - }) -} - -func (s *Server) DeleteBmp(ctx context.Context, arg *api.DeleteBmpRequest) (*api.DeleteBmpResponse, error) { - return &api.DeleteBmpResponse{}, s.bgpServer.DeleteBmp(&config.BmpServerConfig{ - Address: arg.Address, - Port: arg.Port, - }) -} - -func (s *Server) ValidateRib(ctx context.Context, arg *api.ValidateRibRequest) (*api.ValidateRibResponse, error) { - return &api.ValidateRibResponse{}, s.bgpServer.ValidateRib(arg.Prefix) -} - -func (s *Server) AddRpki(ctx context.Context, arg *api.AddRpkiRequest) (*api.AddRpkiResponse, error) { - return &api.AddRpkiResponse{}, s.bgpServer.AddRpki(&config.RpkiServerConfig{ - Address: arg.Address, - Port: arg.Port, - RecordLifetime: arg.Lifetime, - }) -} - -func (s *Server) DeleteRpki(ctx context.Context, arg *api.DeleteRpkiRequest) (*api.DeleteRpkiResponse, error) { - return &api.DeleteRpkiResponse{}, s.bgpServer.DeleteRpki(&config.RpkiServerConfig{ - Address: arg.Address, - Port: arg.Port, - }) -} - -func (s *Server) EnableRpki(ctx context.Context, arg *api.EnableRpkiRequest) (*api.EnableRpkiResponse, error) { - return &api.EnableRpkiResponse{}, s.bgpServer.EnableRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) -} - -func (s *Server) DisableRpki(ctx context.Context, arg *api.DisableRpkiRequest) (*api.DisableRpkiResponse, error) { - return &api.DisableRpkiResponse{}, s.bgpServer.DisableRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) -} - -func (s *Server) ResetRpki(ctx context.Context, arg *api.ResetRpkiRequest) (*api.ResetRpkiResponse, error) { - return &api.ResetRpkiResponse{}, s.bgpServer.ResetRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) -} - -func (s *Server) SoftResetRpki(ctx context.Context, arg *api.SoftResetRpkiRequest) (*api.SoftResetRpkiResponse, error) { - return &api.SoftResetRpkiResponse{}, s.bgpServer.SoftResetRpki(&config.RpkiServerConfig{ - Address: arg.Address, - }) -} - -func (s *Server) GetRpki(ctx context.Context, arg *api.GetRpkiRequest) (*api.GetRpkiResponse, error) { - servers, err := s.bgpServer.GetRpki() - if err != nil { - return nil, err - } - l := make([]*api.Rpki, 0, len(servers)) - 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: strconv.Itoa(int(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, - }, - } - l = append(l, rpki) - } - return &api.GetRpkiResponse{Servers: l}, nil -} - -func (s *Server) GetRoa(ctx context.Context, arg *api.GetRoaRequest) (*api.GetRoaResponse, error) { - roas, err := s.bgpServer.GetRoa(bgp.RouteFamily(arg.Family)) - if err != nil { - return nil, err - } - l := make([]*api.Roa, 0, len(roas)) - for _, r := range roas { - host, port, _ := net.SplitHostPort(r.Src) - l = append(l, &api.Roa{ - As: r.AS, - Maxlen: uint32(r.MaxLen), - Prefixlen: uint32(r.Prefix.Length), - Prefix: r.Prefix.Prefix.String(), - Conf: &api.RPKIConf{ - Address: host, - RemotePort: port, - }, - }) - } - return &api.GetRoaResponse{Roas: l}, nil -} - -func (s *Server) GetVrf(ctx context.Context, arg *api.GetVrfRequest) (*api.GetVrfResponse, error) { - toApi := func(v *table.Vrf) *api.Vrf { - f := func(rts []bgp.ExtendedCommunityInterface) [][]byte { - ret := make([][]byte, 0, len(rts)) - for _, rt := range rts { - b, _ := rt.Serialize() - ret = append(ret, b) - } - return ret - } - rd, _ := v.Rd.Serialize() - return &api.Vrf{ - Name: v.Name, - Rd: rd, - ImportRt: f(v.ImportRt), - ExportRt: f(v.ExportRt), - } - } - vrfs := s.bgpServer.GetVrf() - l := make([]*api.Vrf, 0, len(vrfs)) - for _, v := range vrfs { - l = append(l, toApi(v)) - } - return &api.GetVrfResponse{Vrfs: l}, nil -} - -func (s *Server) AddVrf(ctx context.Context, arg *api.AddVrfRequest) (r *api.AddVrfResponse, err error) { - rd := bgp.GetRouteDistinguisher(arg.Vrf.Rd) - f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) { - ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs)) - for _, rt := range bufs { - r, err := bgp.ParseExtended(rt) - if err != nil { - return nil, err - } - ret = append(ret, r) - } - return ret, nil - } - im, err := f(arg.Vrf.ImportRt) - if err != nil { - return &api.AddVrfResponse{}, err - } - ex, err := f(arg.Vrf.ExportRt) - if err != nil { - return &api.AddVrfResponse{}, err - } - return &api.AddVrfResponse{}, s.bgpServer.AddVrf(arg.Vrf.Name, rd, im, ex) -} - -func (s *Server) DeleteVrf(ctx context.Context, arg *api.DeleteVrfRequest) (*api.DeleteVrfResponse, error) { - return &api.DeleteVrfResponse{}, s.bgpServer.DeleteVrf(arg.Vrf.Name) -} - -func (s *Server) AddNeighbor(ctx context.Context, arg *api.AddNeighborRequest) (*api.AddNeighborResponse, error) { - c, err := func(a *api.Peer) (config.Neighbor, error) { - pconf := config.Neighbor{} - if a.Conf != nil { - pconf.Config.NeighborAddress = a.Conf.NeighborAddress - pconf.Config.PeerAs = a.Conf.PeerAs - pconf.Config.LocalAs = a.Conf.LocalAs - - if pconf.Config.PeerAs != pconf.Config.LocalAs { - pconf.Config.PeerType = config.PEER_TYPE_EXTERNAL - } else { - pconf.Config.PeerType = config.PEER_TYPE_INTERNAL - } - pconf.Config.AuthPassword = a.Conf.AuthPassword - pconf.Config.RemovePrivateAs = config.RemovePrivateAsOption(a.Conf.RemovePrivateAs) - pconf.Config.RouteFlapDamping = a.Conf.RouteFlapDamping - pconf.Config.SendCommunity = config.CommunityType(a.Conf.SendCommunity) - pconf.Config.Description = a.Conf.Description - pconf.Config.PeerGroup = a.Conf.PeerGroup - pconf.Config.NeighborAddress = a.Conf.NeighborAddress - } - if a.Timers != nil { - if a.Timers.Config != nil { - pconf.Timers.Config.ConnectRetry = float64(a.Timers.Config.ConnectRetry) - pconf.Timers.Config.HoldTime = float64(a.Timers.Config.HoldTime) - pconf.Timers.Config.KeepaliveInterval = float64(a.Timers.Config.KeepaliveInterval) - pconf.Timers.Config.MinimumAdvertisementInterval = float64(a.Timers.Config.MinimumAdvertisementInterval) - } - } else { - pconf.Timers.Config.ConnectRetry = float64(config.DEFAULT_CONNECT_RETRY) - pconf.Timers.Config.HoldTime = float64(config.DEFAULT_HOLDTIME) - pconf.Timers.Config.KeepaliveInterval = float64(config.DEFAULT_HOLDTIME / 3) - } - if a.RouteReflector != nil { - pconf.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(a.RouteReflector.RouteReflectorClusterId) - pconf.RouteReflector.Config.RouteReflectorClient = a.RouteReflector.RouteReflectorClient - } - if a.RouteServer != nil { - pconf.RouteServer.Config.RouteServerClient = a.RouteServer.RouteServerClient - } - if a.ApplyPolicy != nil { - if a.ApplyPolicy.ImportPolicy != nil { - pconf.ApplyPolicy.Config.DefaultImportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ImportPolicy.Default) - for _, p := range a.ApplyPolicy.ImportPolicy.Policies { - pconf.ApplyPolicy.Config.ImportPolicyList = append(pconf.ApplyPolicy.Config.ImportPolicyList, p.Name) - } - } - if a.ApplyPolicy.ExportPolicy != nil { - pconf.ApplyPolicy.Config.DefaultExportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ExportPolicy.Default) - for _, p := range a.ApplyPolicy.ExportPolicy.Policies { - pconf.ApplyPolicy.Config.ExportPolicyList = append(pconf.ApplyPolicy.Config.ExportPolicyList, p.Name) - } - } - if a.ApplyPolicy.InPolicy != nil { - pconf.ApplyPolicy.Config.DefaultInPolicy = config.DefaultPolicyType(a.ApplyPolicy.InPolicy.Default) - for _, p := range a.ApplyPolicy.InPolicy.Policies { - pconf.ApplyPolicy.Config.InPolicyList = append(pconf.ApplyPolicy.Config.InPolicyList, p.Name) - } - } - } - if a.Families != nil { - for _, family := range a.Families { - name, ok := bgp.AddressFamilyNameMap[bgp.RouteFamily(family)] - if !ok { - return pconf, fmt.Errorf("invalid address family: %d", family) - } - cAfiSafi := config.AfiSafi{ - Config: config.AfiSafiConfig{ - AfiSafiName: config.AfiSafiType(name), - }, - } - pconf.AfiSafis = append(pconf.AfiSafis, cAfiSafi) - } - } else { - if net.ParseIP(a.Conf.NeighborAddress).To4() != nil { - pconf.AfiSafis = []config.AfiSafi{ - config.AfiSafi{ - Config: config.AfiSafiConfig{ - AfiSafiName: "ipv4-unicast", - }, - }, - } - } else { - pconf.AfiSafis = []config.AfiSafi{ - config.AfiSafi{ - Config: config.AfiSafiConfig{ - AfiSafiName: "ipv6-unicast", - }, - }, - } - } - } - if a.Transport != nil { - pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress - pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode - } else { - if net.ParseIP(a.Conf.NeighborAddress).To4() != nil { - pconf.Transport.Config.LocalAddress = "0.0.0.0" - } else { - pconf.Transport.Config.LocalAddress = "::" - } - } - if a.EbgpMultihop != nil { - pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled - pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl) - } - return pconf, nil - }(arg.Peer) - if err != nil { - return nil, err - } - return &api.AddNeighborResponse{}, s.bgpServer.AddNeighbor(&c) -} - -func (s *Server) DeleteNeighbor(ctx context.Context, arg *api.DeleteNeighborRequest) (*api.DeleteNeighborResponse, error) { - return &api.DeleteNeighborResponse{}, s.bgpServer.DeleteNeighbor(&config.Neighbor{Config: config.NeighborConfig{ - NeighborAddress: arg.Peer.Conf.NeighborAddress, - }}) -} - -func NewPrefixFromApiStruct(a *api.Prefix) (*table.Prefix, error) { - addr, prefix, err := net.ParseCIDR(a.IpPrefix) - if err != nil { - return nil, err - } - rf := bgp.RF_IPv4_UC - if addr.To4() == nil { - rf = bgp.RF_IPv6_UC - } - return &table.Prefix{ - Prefix: prefix, - AddressFamily: rf, - MasklengthRangeMin: uint8(a.MaskLengthMin), - MasklengthRangeMax: uint8(a.MaskLengthMax), - }, nil -} - -func NewDefinedSetFromApiStruct(a *api.DefinedSet) (table.DefinedSet, error) { - if a.Name == "" { - return nil, fmt.Errorf("empty neighbor set name") - } - switch table.DefinedType(a.Type) { - case table.DEFINED_TYPE_PREFIX: - prefixes := make([]*table.Prefix, 0, len(a.Prefixes)) - for _, p := range a.Prefixes { - prefix, err := NewPrefixFromApiStruct(p) - if err != nil { - return nil, err - } - prefixes = append(prefixes, prefix) - } - return table.NewPrefixSetFromApiStruct(a.Name, prefixes) - case table.DEFINED_TYPE_NEIGHBOR: - list := make([]net.IP, 0, len(a.List)) - for _, x := range a.List { - addr := net.ParseIP(x) - if addr == nil { - return nil, fmt.Errorf("invalid ip address format: %s", x) - } - list = append(list, addr) - } - return table.NewNeighborSetFromApiStruct(a.Name, list) - case table.DEFINED_TYPE_AS_PATH: - return table.NewAsPathSet(config.AsPathSet{ - AsPathSetName: a.Name, - AsPathList: a.List, - }) - case table.DEFINED_TYPE_COMMUNITY: - return table.NewCommunitySet(config.CommunitySet{ - CommunitySetName: a.Name, - CommunityList: a.List, - }) - case table.DEFINED_TYPE_EXT_COMMUNITY: - return table.NewExtCommunitySet(config.ExtCommunitySet{ - ExtCommunitySetName: a.Name, - ExtCommunityList: a.List, - }) - default: - return nil, fmt.Errorf("invalid defined type") - } -} - -func (s *Server) GetDefinedSet(ctx context.Context, arg *api.GetDefinedSetRequest) (*api.GetDefinedSetResponse, error) { - cd, err := s.bgpServer.GetDefinedSet(table.DefinedType(arg.Type)) - 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 { - exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)") - elems := exp.FindStringSubmatch(p.MasklengthRange) - min, _ := strconv.Atoi(elems[1]) - max, _ := strconv.Atoi(elems[2]) - - 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.AsPathSets { - ad := &api.DefinedSet{ - Type: api.DefinedType_AS_PATH, - Name: cs.AsPathSetName, - List: cs.AsPathList, - } - sets = append(sets, ad) - } - - return &api.GetDefinedSetResponse{Sets: sets}, nil -} - -func (s *Server) AddDefinedSet(ctx context.Context, arg *api.AddDefinedSetRequest) (*api.AddDefinedSetResponse, error) { - set, err := NewDefinedSetFromApiStruct(arg.Set) - if err != nil { - return nil, err - } - return &api.AddDefinedSetResponse{}, s.bgpServer.AddDefinedSet(set) -} - -func (s *Server) DeleteDefinedSet(ctx context.Context, arg *api.DeleteDefinedSetRequest) (*api.DeleteDefinedSetResponse, error) { - set, err := NewDefinedSetFromApiStruct(arg.Set) - if err != nil { - return nil, err - } - return &api.DeleteDefinedSetResponse{}, s.bgpServer.DeleteDefinedSet(set, arg.All) -} - -func (s *Server) ReplaceDefinedSet(ctx context.Context, arg *api.ReplaceDefinedSetRequest) (*api.ReplaceDefinedSetResponse, error) { - set, err := NewDefinedSetFromApiStruct(arg.Set) - if err != nil { - return nil, err - } - return &api.ReplaceDefinedSetResponse{}, s.bgpServer.ReplaceDefinedSet(set) -} - -func toStatementApi(s *config.Statement) *api.Statement { - cs := &api.Conditions{} - if s.Conditions.MatchPrefixSet.PrefixSet != "" { - cs.PrefixSet = &api.MatchSet{ - Type: api.MatchType(s.Conditions.MatchPrefixSet.MatchSetOptions.ToInt()), - Name: s.Conditions.MatchPrefixSet.PrefixSet, - } - } - if s.Conditions.MatchNeighborSet.NeighborSet != "" { - cs.NeighborSet = &api.MatchSet{ - Type: api.MatchType(s.Conditions.MatchNeighborSet.MatchSetOptions.ToInt()), - Name: s.Conditions.MatchNeighborSet.NeighborSet, - } - } - if s.Conditions.BgpConditions.AsPathLength.Operator != "" { - cs.AsPathLength = &api.AsPathLength{ - Length: s.Conditions.BgpConditions.AsPathLength.Value, - Type: api.AsPathLengthType(s.Conditions.BgpConditions.AsPathLength.Operator.ToInt()), - } - } - if s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet != "" { - cs.AsPathSet = &api.MatchSet{ - Type: api.MatchType(s.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions.ToInt()), - Name: s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet, - } - } - if s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet != "" { - cs.CommunitySet = &api.MatchSet{ - Type: api.MatchType(s.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions.ToInt()), - Name: s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet, - } - } - if s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet != "" { - cs.CommunitySet = &api.MatchSet{ - Type: api.MatchType(s.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions.ToInt()), - Name: s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet, - } - } - cs.RpkiResult = int32(s.Conditions.BgpConditions.RpkiValidationResult.ToInt()) - as := &api.Actions{ - RouteAction: func() api.RouteAction { - if s.Actions.RouteDisposition.AcceptRoute { - return api.RouteAction_ACCEPT - } - return api.RouteAction_REJECT - }(), - Community: func() *api.CommunityAction { - if len(s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList) == 0 { - return nil - } - return &api.CommunityAction{ - Type: api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetCommunity.Options)]), - Communities: s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList} - }(), - Med: func() *api.MedAction { - if len(string(s.Actions.BgpActions.SetMed)) == 0 { - return nil - } - exp := regexp.MustCompile("^(\\+|\\-)?(\\d+)$") - elems := exp.FindStringSubmatch(string(s.Actions.BgpActions.SetMed)) - action := api.MedActionType_MED_REPLACE - switch elems[1] { - case "+", "-": - action = api.MedActionType_MED_MOD - } - value, _ := strconv.Atoi(string(s.Actions.BgpActions.SetMed)) - return &api.MedAction{ - Value: int64(value), - Type: action, - } - }(), - AsPrepend: func() *api.AsPrependAction { - if len(s.Actions.BgpActions.SetAsPathPrepend.As) == 0 { - return nil - } - asn := 0 - useleft := false - if s.Actions.BgpActions.SetAsPathPrepend.As != "last-as" { - asn, _ = strconv.Atoi(s.Actions.BgpActions.SetAsPathPrepend.As) - } else { - useleft = true - } - return &api.AsPrependAction{ - Asn: uint32(asn), - Repeat: uint32(s.Actions.BgpActions.SetAsPathPrepend.RepeatN), - UseLeftMost: useleft, - } - }(), - ExtCommunity: func() *api.CommunityAction { - if len(s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList) == 0 { - return nil - } - return &api.CommunityAction{ - Type: api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetExtCommunity.Options)]), - Communities: s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList, - } - }(), - Nexthop: func() *api.NexthopAction { - if len(string(s.Actions.BgpActions.SetNextHop)) == 0 { - return nil - } - - if string(s.Actions.BgpActions.SetNextHop) == "self" { - return &api.NexthopAction{ - Self: true, - } - } - return &api.NexthopAction{ - Address: string(s.Actions.BgpActions.SetNextHop), - } - }(), - LocalPref: func() *api.LocalPrefAction { - if s.Actions.BgpActions.SetLocalPref == 0 { - return nil - } - return &api.LocalPrefAction{Value: s.Actions.BgpActions.SetLocalPref} - }(), - } - return &api.Statement{ - Name: s.Name, - Conditions: cs, - Actions: as, - } -} - -func toConfigMatchSetOption(a api.MatchType) (config.MatchSetOptionsType, error) { - var typ config.MatchSetOptionsType - switch a { - case api.MatchType_ANY: - typ = config.MATCH_SET_OPTIONS_TYPE_ANY - case api.MatchType_ALL: - typ = config.MATCH_SET_OPTIONS_TYPE_ALL - case api.MatchType_INVERT: - typ = config.MATCH_SET_OPTIONS_TYPE_INVERT - default: - return typ, fmt.Errorf("invalid match type") - } - return typ, nil -} - -func toConfigMatchSetOptionRestricted(a api.MatchType) (config.MatchSetOptionsRestrictedType, error) { - var typ config.MatchSetOptionsRestrictedType - switch a { - case api.MatchType_ANY: - typ = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY - case api.MatchType_INVERT: - typ = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT - default: - return typ, fmt.Errorf("invalid match type") - } - return typ, nil -} - -func NewPrefixConditionFromApiStruct(a *api.MatchSet) (*table.PrefixCondition, error) { - if a == nil { - return nil, nil - } - typ, err := toConfigMatchSetOptionRestricted(a.Type) - if err != nil { - return nil, err - } - c := config.MatchPrefixSet{ - PrefixSet: a.Name, - MatchSetOptions: typ, - } - return table.NewPrefixCondition(c) -} - -func NewNeighborConditionFromApiStruct(a *api.MatchSet) (*table.NeighborCondition, error) { - if a == nil { - return nil, nil - } - typ, err := toConfigMatchSetOptionRestricted(a.Type) - if err != nil { - return nil, err - } - c := config.MatchNeighborSet{ - NeighborSet: a.Name, - MatchSetOptions: typ, - } - return table.NewNeighborCondition(c) -} - -func NewAsPathLengthConditionFromApiStruct(a *api.AsPathLength) (*table.AsPathLengthCondition, error) { - if a == nil { - return nil, nil - } - return table.NewAsPathLengthCondition(config.AsPathLength{ - Operator: config.IntToAttributeComparisonMap[int(a.Type)], - Value: a.Length, - }) -} - -func NewAsPathConditionFromApiStruct(a *api.MatchSet) (*table.AsPathCondition, error) { - if a == nil { - return nil, nil - } - typ, err := toConfigMatchSetOption(a.Type) - if err != nil { - return nil, err - } - c := config.MatchAsPathSet{ - AsPathSet: a.Name, - MatchSetOptions: typ, - } - return table.NewAsPathCondition(c) -} - -func NewRpkiValidationConditionFromApiStruct(a int32) (*table.RpkiValidationCondition, error) { - if a < 1 { - return nil, nil - } - return table.NewRpkiValidationCondition(config.IntToRpkiValidationResultTypeMap[int(a)]) -} - -func NewCommunityConditionFromApiStruct(a *api.MatchSet) (*table.CommunityCondition, error) { - if a == nil { - return nil, nil - } - typ, err := toConfigMatchSetOption(a.Type) - if err != nil { - return nil, err - } - c := config.MatchCommunitySet{ - CommunitySet: a.Name, - MatchSetOptions: typ, - } - return table.NewCommunityCondition(c) -} - -func NewExtCommunityConditionFromApiStruct(a *api.MatchSet) (*table.ExtCommunityCondition, error) { - if a == nil { - return nil, nil - } - typ, err := toConfigMatchSetOption(a.Type) - if err != nil { - return nil, err - } - c := config.MatchExtCommunitySet{ - ExtCommunitySet: a.Name, - MatchSetOptions: typ, - } - return table.NewExtCommunityCondition(c) -} - -func NewRoutingActionFromApiStruct(a api.RouteAction) (*table.RoutingAction, error) { - if a == api.RouteAction_NONE { - return nil, nil - } - accept := false - if a == api.RouteAction_ACCEPT { - accept = true - } - return &table.RoutingAction{ - AcceptRoute: accept, - }, nil -} - -func NewCommunityActionFromApiStruct(a *api.CommunityAction) (*table.CommunityAction, error) { - if a == nil { - return nil, nil - } - return table.NewCommunityAction(config.SetCommunity{ - Options: string(config.IntToBgpSetCommunityOptionTypeMap[int(a.Type)]), - SetCommunityMethod: config.SetCommunityMethod{ - CommunitiesList: a.Communities, - }, - }) -} - -func NewExtCommunityActionFromApiStruct(a *api.CommunityAction) (*table.ExtCommunityAction, error) { - if a == nil { - return nil, nil - } - return table.NewExtCommunityAction(config.SetExtCommunity{ - Options: string(config.IntToBgpSetCommunityOptionTypeMap[int(a.Type)]), - SetExtCommunityMethod: config.SetExtCommunityMethod{ - CommunitiesList: a.Communities, - }, - }) -} - -func NewMedActionFromApiStruct(a *api.MedAction) (*table.MedAction, error) { - if a == nil { - return nil, nil - } - return table.NewMedActionFromApiStruct(table.MedActionType(a.Type), int(a.Value)), nil -} - -func NewLocalPrefActionFromApiStruct(a *api.LocalPrefAction) (*table.LocalPrefAction, error) { - if a == nil || a.Value == 0 { - return nil, nil - } - return table.NewLocalPrefAction(a.Value) -} - -func NewAsPathPrependActionFromApiStruct(a *api.AsPrependAction) (*table.AsPathPrependAction, error) { - if a == nil { - return nil, nil - } - return table.NewAsPathPrependAction(config.SetAsPathPrepend{ - RepeatN: uint8(a.Repeat), - As: func() string { - if a.UseLeftMost { - return "last-as" - } - return fmt.Sprintf("%d", a.Asn) - }(), - }) -} - -func NewNexthopActionFromApiStruct(a *api.NexthopAction) (*table.NexthopAction, error) { - if a == nil { - return nil, nil - } - return table.NewNexthopAction(config.BgpNextHopType( - func() string { - if a.Self { - return "self" - } - return a.Address - }(), - )) -} - -func NewStatementFromApiStruct(a *api.Statement) (*table.Statement, error) { - if a.Name == "" { - return nil, fmt.Errorf("empty statement name") - } - var ra table.Action - var as []table.Action - var cs []table.Condition - var err error - if a.Conditions != nil { - cfs := []func() (table.Condition, error){ - func() (table.Condition, error) { - return NewPrefixConditionFromApiStruct(a.Conditions.PrefixSet) - }, - func() (table.Condition, error) { - return NewNeighborConditionFromApiStruct(a.Conditions.NeighborSet) - }, - func() (table.Condition, error) { - return NewAsPathLengthConditionFromApiStruct(a.Conditions.AsPathLength) - }, - func() (table.Condition, error) { - return NewRpkiValidationConditionFromApiStruct(a.Conditions.RpkiResult) - }, - func() (table.Condition, error) { - return NewAsPathConditionFromApiStruct(a.Conditions.AsPathSet) - }, - func() (table.Condition, error) { - return NewCommunityConditionFromApiStruct(a.Conditions.CommunitySet) - }, - func() (table.Condition, error) { - return NewExtCommunityConditionFromApiStruct(a.Conditions.ExtCommunitySet) - }, - } - cs = make([]table.Condition, 0, len(cfs)) - for _, f := range cfs { - c, err := f() - if err != nil { - return nil, err - } - if !reflect.ValueOf(c).IsNil() { - cs = append(cs, c) - } - } - } - if a.Actions != nil { - ra, err = NewRoutingActionFromApiStruct(a.Actions.RouteAction) - if err != nil { - return nil, err - } - afs := []func() (table.Action, error){ - func() (table.Action, error) { - return NewCommunityActionFromApiStruct(a.Actions.Community) - }, - func() (table.Action, error) { - return NewExtCommunityActionFromApiStruct(a.Actions.ExtCommunity) - }, - func() (table.Action, error) { - return NewMedActionFromApiStruct(a.Actions.Med) - }, - func() (table.Action, error) { - return NewLocalPrefActionFromApiStruct(a.Actions.LocalPref) - }, - func() (table.Action, error) { - return NewAsPathPrependActionFromApiStruct(a.Actions.AsPrepend) - }, - func() (table.Action, error) { - return NewNexthopActionFromApiStruct(a.Actions.Nexthop) - }, - } - as = make([]table.Action, 0, len(afs)) - for _, f := range afs { - a, err := f() - if err != nil { - return nil, err - } - if !reflect.ValueOf(a).IsNil() { - as = append(as, a) - } - } - } - return &table.Statement{ - Name: a.Name, - Conditions: cs, - RouteAction: ra, - ModActions: as, - }, nil -} - -func (s *Server) GetStatement(ctx context.Context, arg *api.GetStatementRequest) (*api.GetStatementResponse, error) { - l := make([]*api.Statement, 0) - for _, s := range s.bgpServer.GetStatement() { - l = append(l, toStatementApi(s)) - } - return &api.GetStatementResponse{Statements: l}, nil -} - -func (s *Server) AddStatement(ctx context.Context, arg *api.AddStatementRequest) (*api.AddStatementResponse, error) { - st, err := NewStatementFromApiStruct(arg.Statement) - if err == nil { - err = s.bgpServer.AddStatement(st) - } - return &api.AddStatementResponse{}, err -} - -func (s *Server) DeleteStatement(ctx context.Context, arg *api.DeleteStatementRequest) (*api.DeleteStatementResponse, error) { - st, err := NewStatementFromApiStruct(arg.Statement) - if err == nil { - err = s.bgpServer.DeleteStatement(st, arg.All) - } - return &api.DeleteStatementResponse{}, err -} - -func (s *Server) ReplaceStatement(ctx context.Context, arg *api.ReplaceStatementRequest) (*api.ReplaceStatementResponse, error) { - st, err := NewStatementFromApiStruct(arg.Statement) - if err == nil { - err = s.bgpServer.ReplaceStatement(st) - } - return &api.ReplaceStatementResponse{}, err -} - -func toPolicyApi(p *config.PolicyDefinition) *api.Policy { - return &api.Policy{ - Name: p.Name, - Statements: func() []*api.Statement { - l := make([]*api.Statement, 0) - for _, s := range p.Statements { - l = append(l, toStatementApi(&s)) - } - return l - }(), - } -} - -func NewPolicyFromApiStruct(a *api.Policy) (*table.Policy, error) { - if a.Name == "" { - return nil, fmt.Errorf("empty policy name") - } - stmts := make([]*table.Statement, 0, len(a.Statements)) - for idx, x := range a.Statements { - if x.Name == "" { - x.Name = fmt.Sprintf("%s_stmt%d", a.Name, idx) - } - y, err := NewStatementFromApiStruct(x) - if err != nil { - return nil, err - } - stmts = append(stmts, y) - } - return &table.Policy{ - Name: a.Name, - Statements: stmts, - }, nil -} - -func (s *Server) GetPolicy(ctx context.Context, arg *api.GetPolicyRequest) (*api.GetPolicyResponse, error) { - l := make([]*api.Policy, 0) - for _, p := range s.bgpServer.GetPolicy() { - l = append(l, toPolicyApi(p)) - } - return &api.GetPolicyResponse{Policies: l}, nil -} - -func (s *Server) AddPolicy(ctx context.Context, arg *api.AddPolicyRequest) (*api.AddPolicyResponse, error) { - x, err := NewPolicyFromApiStruct(arg.Policy) - if err != nil { - return nil, err - } - return &api.AddPolicyResponse{}, s.bgpServer.AddPolicy(x, arg.ReferExistingStatements) -} - -func (s *Server) DeletePolicy(ctx context.Context, arg *api.DeletePolicyRequest) (*api.DeletePolicyResponse, error) { - x, err := NewPolicyFromApiStruct(arg.Policy) - if err != nil { - return nil, err - } - return &api.DeletePolicyResponse{}, s.bgpServer.DeletePolicy(x, arg.All, arg.PreserveStatements) -} - -func (s *Server) ReplacePolicy(ctx context.Context, arg *api.ReplacePolicyRequest) (*api.ReplacePolicyResponse, error) { - x, err := NewPolicyFromApiStruct(arg.Policy) - if err != nil { - return nil, err - } - return &api.ReplacePolicyResponse{}, s.bgpServer.ReplacePolicy(x, arg.ReferExistingStatements, arg.PreserveStatements) -} - -func toPolicyAssignmentName(a *api.PolicyAssignment) (string, table.PolicyDirection, error) { - switch a.Resource { - case api.Resource_GLOBAL: - switch a.Type { - case api.PolicyType_IMPORT: - return "", table.POLICY_DIRECTION_IMPORT, nil - case api.PolicyType_EXPORT: - return "", table.POLICY_DIRECTION_EXPORT, nil - default: - return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid policy type") - } - case api.Resource_LOCAL: - switch a.Type { - case api.PolicyType_IN: - return a.Name, table.POLICY_DIRECTION_IN, nil - case api.PolicyType_IMPORT: - return a.Name, table.POLICY_DIRECTION_IMPORT, nil - case api.PolicyType_EXPORT: - return a.Name, table.POLICY_DIRECTION_EXPORT, nil - default: - return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid policy type") - } - default: - return "", table.POLICY_DIRECTION_NONE, fmt.Errorf("invalid resource type") - } - -} - -func (s *Server) GetPolicyAssignment(ctx context.Context, arg *api.GetPolicyAssignmentRequest) (*api.GetPolicyAssignmentResponse, error) { - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - d, a, err := s.bgpServer.GetPolicyAssignment(name, dir) - if err != nil { - return nil, err - } - return &api.GetPolicyAssignmentResponse{ - Assignment: &api.PolicyAssignment{ - Default: func() api.RouteAction { - switch d { - case table.ROUTE_TYPE_ACCEPT: - return api.RouteAction_ACCEPT - case table.ROUTE_TYPE_REJECT: - return api.RouteAction_REJECT - } - return api.RouteAction_NONE - - }(), - Policies: func() []*api.Policy { - l := make([]*api.Policy, 0) - for _, p := range a { - l = append(l, toPolicyApi(p)) - } - return l - }(), - }, - }, err -} - -func defaultRouteType(d api.RouteAction) table.RouteType { - switch d { - case api.RouteAction_ACCEPT: - return table.ROUTE_TYPE_ACCEPT - case api.RouteAction_REJECT: - return table.ROUTE_TYPE_REJECT - default: - return table.ROUTE_TYPE_NONE - } -} - -func toPolicyDefinition(policies []*api.Policy) []*config.PolicyDefinition { - l := make([]*config.PolicyDefinition, 0, len(policies)) - for _, p := range policies { - l = append(l, &config.PolicyDefinition{Name: p.Name}) - } - return l -} - -func (s *Server) AddPolicyAssignment(ctx context.Context, arg *api.AddPolicyAssignmentRequest) (*api.AddPolicyAssignmentResponse, error) { - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - return &api.AddPolicyAssignmentResponse{}, s.bgpServer.AddPolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), defaultRouteType(arg.Assignment.Default)) -} - -func (s *Server) DeletePolicyAssignment(ctx context.Context, arg *api.DeletePolicyAssignmentRequest) (*api.DeletePolicyAssignmentResponse, error) { - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - return &api.DeletePolicyAssignmentResponse{}, s.bgpServer.DeletePolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), arg.All) -} - -func (s *Server) ReplacePolicyAssignment(ctx context.Context, arg *api.ReplacePolicyAssignmentRequest) (*api.ReplacePolicyAssignmentResponse, error) { - name, dir, err := toPolicyAssignmentName(arg.Assignment) - if err != nil { - return nil, err - } - return &api.ReplacePolicyAssignmentResponse{}, s.bgpServer.ReplacePolicyAssignment(name, dir, toPolicyDefinition(arg.Assignment.Policies), defaultRouteType(arg.Assignment.Default)) -} - -func (s *Server) GetServer(ctx context.Context, arg *api.GetServerRequest) (*api.GetServerResponse, error) { - g := s.bgpServer.GetServer() - return &api.GetServerResponse{ - Global: &api.Global{ - As: g.Config.As, - RouterId: g.Config.RouterId, - ListenPort: g.Config.Port, - ListenAddresses: g.Config.LocalAddressList, - MplsLabelMin: g.MplsLabelRange.MinLabel, - MplsLabelMax: g.MplsLabelRange.MaxLabel, - }, - }, nil -} - -func (s *Server) StartServer(ctx context.Context, arg *api.StartServerRequest) (*api.StartServerResponse, error) { - g := arg.Global - if net.ParseIP(g.RouterId) == nil { - return nil, fmt.Errorf("invalid router-id format: %s", g.RouterId) - } - families := make([]config.AfiSafi, 0, len(g.Families)) - for _, f := range g.Families { - name := config.AfiSafiType(bgp.RouteFamily(f).String()) - families = append(families, config.AfiSafi{ - Config: config.AfiSafiConfig{ - AfiSafiName: name, - Enabled: true, - }, - State: config.AfiSafiState{ - AfiSafiName: name, - }, - }) - } - b := &config.BgpConfigSet{ - Global: config.Global{ - Config: config.GlobalConfig{ - As: g.As, - RouterId: g.RouterId, - Port: g.ListenPort, - LocalAddressList: g.ListenAddresses, - }, - MplsLabelRange: config.MplsLabelRange{ - MinLabel: g.MplsLabelMin, - MaxLabel: g.MplsLabelMax, - }, - AfiSafis: families, - }, - } - if err := config.SetDefaultConfigValues(nil, b); err != nil { - return nil, err - } - return &api.StartServerResponse{}, s.bgpServer.Start(&b.Global) -} - -func (s *Server) StopServer(ctx context.Context, arg *api.StopServerRequest) (*api.StopServerResponse, error) { - return &api.StopServerResponse{}, s.bgpServer.Stop() -} |