diff options
author | Yuji Oshima <yuji.oshima0x3fd@gmail.com> | 2015-10-29 17:26:01 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-10-29 17:26:01 +0900 |
commit | b780fed28a735fa97cfbb220769f6f2082543674 (patch) | |
tree | b45b5ed4b2c56f93a70c44b7c4404df6e9d22582 /server | |
parent | 645ce47b986cf7296d217bc98af7b4a8446833a9 (diff) |
api: confirm api.Peer to openconfig and add ModPeer api
Signed-off-by: YujiOshima <yuji.oshima0x3fd@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'server')
-rw-r--r-- | server/grpc_server.go | 5 | ||||
-rw-r--r-- | server/peer.go | 114 | ||||
-rw-r--r-- | server/server.go | 172 |
3 files changed, 236 insertions, 55 deletions
diff --git a/server/grpc_server.go b/server/grpc_server.go index f6f233a0..348d11c7 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -40,6 +40,7 @@ const ( REQ_NEIGHBOR_SOFT_RESET_OUT REQ_NEIGHBOR_ENABLE REQ_NEIGHBOR_DISABLE + REQ_MOD_NEIGHBOR REQ_GLOBAL_RIB REQ_MONITOR_GLOBAL_BEST_CHANGED REQ_MONITOR_NEIGHBOR_PEER_STATE @@ -308,6 +309,10 @@ func (s *Server) ModVrf(ctx context.Context, arg *api.ModVrfArguments) (*api.Err return s.mod(REQ_VRF_MOD, arg) } +func (s *Server) ModNeighbor(ctx context.Context, arg *api.ModNeighborArguments) (*api.Error, error) { + return s.mod(REQ_MOD_NEIGHBOR, arg) +} + func (s *Server) GetDefinedSet(ctx context.Context, arg *api.DefinedSet) (*api.DefinedSet, error) { d, err := s.get(REQ_DEFINED_SET, arg) if err != nil { diff --git a/server/peer.go b/server/peer.go index f21ed0bd..26158a1e 100644 --- a/server/peer.go +++ b/server/peer.go @@ -298,26 +298,20 @@ func (peer *Peer) ToApiStruct() *api.Peer { } conf := &api.PeerConf{ - RemoteIp: c.NeighborConfig.NeighborAddress.String(), - Id: peer.peerInfo.ID.To4().String(), - RemoteAs: c.NeighborConfig.PeerAs, - RemoteCap: remoteCap, - LocalCap: localCap, - KeepaliveInterval: uint32(peer.conf.Timers.TimersConfig.KeepaliveInterval), - Holdtime: uint32(peer.conf.Timers.TimersConfig.HoldTime), + NeighborAddress: c.NeighborConfig.NeighborAddress.String(), + PeerAs: c.NeighborConfig.PeerAs, + LocalAs: c.NeighborConfig.LocalAs, + PeerType: uint32(c.NeighborConfig.PeerType), + AuthPassword: c.NeighborConfig.AuthPassword, + RemovePrivateAs: uint32(c.NeighborConfig.RemovePrivateAs), + RouteFlapDamping: c.NeighborConfig.RouteFlapDamping, + SendCommunity: uint32(c.NeighborConfig.SendCommunity), + Description: c.NeighborConfig.Description, + PeerGroup: c.NeighborConfig.PeerGroup, } - s := &c.NeighborState timer := &c.Timers - - uptime := int64(0) - if timer.TimersState.Uptime != 0 { - uptime = int64(time.Now().Sub(time.Unix(timer.TimersState.Uptime, 0)).Seconds()) - } - downtime := int64(0) - if timer.TimersState.Downtime != 0 { - downtime = int64(time.Now().Sub(time.Unix(timer.TimersState.Downtime, 0)).Seconds()) - } + s := &c.NeighborState advertized := uint32(0) received := uint32(0) @@ -334,6 +328,15 @@ func (peer *Peer) ToApiStruct() *api.Peer { } } + uptime := int64(0) + if timer.TimersState.Uptime != 0 { + uptime = int64(time.Now().Sub(time.Unix(timer.TimersState.Uptime, 0)).Seconds()) + } + downtime := int64(0) + if timer.TimersState.Downtime != 0 { + downtime = int64(time.Now().Sub(time.Unix(timer.TimersState.Downtime, 0)).Seconds()) + } + keepalive := uint32(0) if f.negotiatedHoldTime != 0 { if f.negotiatedHoldTime < timer.TimersConfig.HoldTime { @@ -343,38 +346,57 @@ func (peer *Peer) ToApiStruct() *api.Peer { } } - info := &api.PeerInfo{ - BgpState: f.state.String(), - AdminState: f.adminState.String(), - FsmEstablishedTransitions: s.EstablishedCount, - TotalMessageOut: s.Messages.Sent.Total, - TotalMessageIn: s.Messages.Received.Total, - UpdateMessageOut: s.Messages.Sent.Update, - UpdateMessageIn: s.Messages.Received.Update, - KeepAliveMessageOut: s.Messages.Sent.Keepalive, - KeepAliveMessageIn: s.Messages.Received.Keepalive, - OpenMessageOut: s.Messages.Sent.Open, - OpenMessageIn: s.Messages.Received.Open, - NotificationOut: s.Messages.Sent.Notification, - NotificationIn: s.Messages.Received.Notification, - RefreshMessageOut: s.Messages.Sent.Refresh, - RefreshMessageIn: s.Messages.Received.Refresh, - DiscardedOut: s.Messages.Sent.Discarded, - DiscardedIn: s.Messages.Received.Discarded, - Uptime: uptime, - Downtime: downtime, - Received: received, - Accepted: accepted, - Advertized: advertized, - OutQ: uint32(len(peer.outgoing)), - Flops: s.Flops, - NegotiatedHoldtime: uint32(f.negotiatedHoldTime), - KeepaliveInterval: keepalive, + timerconf := &api.TimersConfig{ + ConnectRetry: uint64(timer.TimersConfig.ConnectRetry), + HoldTime: uint64(timer.TimersConfig.HoldTime), + KeepaliveInterval: uint64(keepalive), + MinimumAdvertisementInterval: uint64(timer.TimersConfig.MinimumAdvertisementInterval), + } + + timerstate := &api.TimersState{ + Uptime: uint64(uptime), + Downtime: uint64(downtime), + } + + apitimer := &api.Timers{ + Config: timerconf, + State: timerstate, + } + msgrcv := &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, + } + msgsnt := &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, + } + msg := &api.Messages{ + Received: msgrcv, + Sent: msgsnt, + } + info := &api.PeerState{ + BgpState: f.state.String(), + AdminState: f.adminState.String(), + Messages: msg, + Received: received, + Accepted: accepted, + Advertized: advertized, } return &api.Peer{ - Conf: conf, - Info: info, + Conf: conf, + Info: info, + Timers: apitimer, } } diff --git a/server/server.go b/server/server.go index a14f8395..49b584ca 100644 --- a/server/server.go +++ b/server/server.go @@ -80,6 +80,7 @@ type BgpServer struct { addedPeerCh chan config.Neighbor deletedPeerCh chan config.Neighbor updatedPeerCh chan config.Neighbor + fsmincomingCh chan *fsmMsg rpkiConfigCh chan config.RpkiServers bmpConfigCh chan config.BmpServers dumper *dumper @@ -90,6 +91,7 @@ type BgpServer struct { policy *table.RoutingPolicy broadcastReqs []*GrpcRequest broadcastMsgs []broadcastMsg + listenerMap map[string]*net.TCPListener neighborMap map[string]*Peer globalRib *table.TableManager zclient *zebra.Client @@ -210,12 +212,12 @@ func (server *BgpServer) Serve() { return rfList } server.globalRib = table.NewTableManager(GLOBAL_RIB_NAME, toRFlist(g.AfiSafis.AfiSafiList), g.MplsLabelRange.MinLabel, g.MplsLabelRange.MaxLabel) - listenerMap := make(map[string]*net.TCPListener) + server.listenerMap = make(map[string]*net.TCPListener) acceptCh := make(chan *net.TCPConn) l4, err1 := listenAndAccept("tcp4", server.listenPort, acceptCh) - listenerMap["tcp4"] = l4 + server.listenerMap["tcp4"] = l4 l6, err2 := listenAndAccept("tcp6", server.listenPort, acceptCh) - listenerMap["tcp6"] = l6 + server.listenerMap["tcp6"] = l6 if err1 != nil && err2 != nil { log.Fatal("can't listen either v4 and v6") os.Exit(1) @@ -224,14 +226,14 @@ func (server *BgpServer) Serve() { listener := func(addr net.IP) *net.TCPListener { var l *net.TCPListener if addr.To4() != nil { - l = listenerMap["tcp4"] + l = server.listenerMap["tcp4"] } else { - l = listenerMap["tcp6"] + l = server.listenerMap["tcp6"] } return l } - incoming := make(chan *fsmMsg, 4096) + server.fsmincomingCh = make(chan *fsmMsg, 4096) var senderMsgs []*SenderMsg var zapiMsgCh chan *zebra.Message @@ -367,7 +369,7 @@ func (server *BgpServer) Serve() { } } server.neighborMap[addr] = peer - peer.startFSMHandler(incoming) + peer.startFSMHandler(server.fsmincomingCh) server.broadcastPeerState(peer) case config := <-server.deletedPeerCh: addr := config.NeighborConfig.NeighborAddress.String() @@ -399,13 +401,13 @@ func (server *BgpServer) Serve() { peer := server.neighborMap[addr] peer.conf = config server.setPolicyByConfig(peer, config.ApplyPolicy) - case e := <-incoming: + case e := <-server.fsmincomingCh: peer, found := server.neighborMap[e.MsgSrc] if !found { log.Warn("Can't find the neighbor ", e.MsgSrc) break } - m := server.handleFSMMessage(peer, e, incoming) + m := server.handleFSMMessage(peer, e, server.fsmincomingCh) if len(m) > 0 { senderMsgs = append(senderMsgs, m...) } @@ -1544,6 +1546,15 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { result.Data = err grpcReq.ResponseCh <- result close(grpcReq.ResponseCh) + case REQ_MOD_NEIGHBOR: + m, err := server.handleGrpcModNeighbor(grpcReq) + grpcReq.ResponseCh <- &GrpcResponse{ + ResponseErr: err, + } + if len(m) > 0 { + msgs = append(msgs, m...) + } + close(grpcReq.ResponseCh) case REQ_DEFINED_SET: if err := server.handleGrpcGetDefinedSet(grpcReq); err != nil { grpcReq.ResponseCh <- &GrpcResponse{ @@ -1644,6 +1655,149 @@ func (server *BgpServer) handleGrpcGetDefinedSet(grpcReq *GrpcRequest) error { } return nil } +func (server *BgpServer) handleGrpcModNeighbor(grpcReq *GrpcRequest) (sMsgs []*SenderMsg, err error) { + arg := grpcReq.Data.(*api.ModNeighborArguments) + addr := arg.Peer.Conf.NeighborAddress + n, ok := server.neighborMap[addr] + if arg.Operation != api.Operation_ADD && !ok { + return nil, fmt.Errorf("not found neighbor %s", addr) + } + listener := func(addr net.IP) *net.TCPListener { + var l *net.TCPListener + if addr.To4() != nil { + l = server.listenerMap["tcp4"] + } else { + l = server.listenerMap["tcp6"] + } + return l + } + + switch arg.Operation { + case api.Operation_ADD: + if ok { + return nil, fmt.Errorf("Can't overwrite the exising peer %s", addr) + } else { + log.Infof("Peer %s is added", addr) + } + SetTcpMD5SigSockopts(listener(net.ParseIP(addr)), addr, arg.Peer.Conf.AuthPassword) + var loc *table.TableManager + if arg.Peer.RouteServer != nil { + if arg.Peer.RouteServer.RouteServerClient { + apitoRFlist := func(l []*api.AfiSafi) []bgp.RouteFamily { + rfList := []bgp.RouteFamily{} + for _, rf := range l { + k, _ := bgp.GetRouteFamily(rf.Name) + rfList = append(rfList, k) + } + return rfList + } + loc = table.NewTableManager(addr, apitoRFlist(arg.Peer.Afisafis.Afisafi), server.bgpConfig.Global.MplsLabelRange.MinLabel, server.bgpConfig.Global.MplsLabelRange.MaxLabel) + } else { + loc = server.globalRib + } + } else { + loc = server.globalRib + } + apitoConfig := func(a *api.Peer) config.Neighbor { + var pconf config.Neighbor + if a.Conf != nil { + pconf.NeighborAddress = net.ParseIP(a.Conf.NeighborAddress) + pconf.NeighborConfig.PeerAs = a.Conf.PeerAs + pconf.NeighborConfig.LocalAs = a.Conf.LocalAs + if pconf.NeighborConfig.PeerAs != server.bgpConfig.Global.GlobalConfig.As { + pconf.NeighborConfig.PeerType = config.PEER_TYPE_EXTERNAL + } else { + pconf.NeighborConfig.PeerType = config.PEER_TYPE_INTERNAL + } + pconf.NeighborConfig.AuthPassword = a.Conf.AuthPassword + pconf.NeighborConfig.RemovePrivateAs = config.RemovePrivateAsOption(a.Conf.RemovePrivateAs) + pconf.NeighborConfig.RouteFlapDamping = a.Conf.RouteFlapDamping + pconf.NeighborConfig.SendCommunity = config.CommunityType(a.Conf.SendCommunity) + pconf.NeighborConfig.Description = a.Conf.Description + pconf.NeighborConfig.PeerGroup = a.Conf.PeerGroup + pconf.NeighborConfig.NeighborAddress = net.ParseIP(a.Conf.NeighborAddress) + } + if a.Timers != nil { + if a.Timers.Config != nil { + pconf.Timers.TimersConfig.ConnectRetry = float64(a.Timers.Config.ConnectRetry) + pconf.Timers.TimersConfig.HoldTime = float64(a.Timers.Config.HoldTime) + pconf.Timers.TimersConfig.KeepaliveInterval = float64(a.Timers.Config.KeepaliveInterval) + pconf.Timers.TimersConfig.MinimumAdvertisementInterval = float64(a.Timers.Config.MinimumAdvertisementInterval) + } + } else { + pconf.Timers.TimersConfig.ConnectRetry = float64(config.DEFAULT_CONNECT_RETRY) + pconf.Timers.TimersConfig.HoldTime = float64(config.DEFAULT_HOLDTIME) + pconf.Timers.TimersConfig.KeepaliveInterval = float64(config.DEFAULT_HOLDTIME / 3) + } + if a.RouteReflector != nil { + pconf.RouteReflector.RouteReflectorConfig.RouteReflectorClusterId = config.RrClusterIdType(a.RouteReflector.RouteReflectorClusterId) + pconf.RouteReflector.RouteReflectorConfig.RouteReflectorClient = a.RouteReflector.RouteReflectorClient + } + if a.RouteServer != nil { + pconf.RouteServer.RouteServerConfig.RouteServerClient = a.RouteServer.RouteServerClient + } + if a.ApplyPolicy != nil { + if a.ApplyPolicy.ImportPolicy != nil { + pconf.ApplyPolicy.ApplyPolicyConfig.DefaultImportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ImportPolicy.Default) + for _, p := range a.ApplyPolicy.ImportPolicy.Policies { + pconf.ApplyPolicy.ApplyPolicyConfig.ImportPolicy = append(pconf.ApplyPolicy.ApplyPolicyConfig.ImportPolicy, p.Name) + } + } + if a.ApplyPolicy.ExportPolicy != nil { + pconf.ApplyPolicy.ApplyPolicyConfig.DefaultExportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ExportPolicy.Default) + for _, p := range a.ApplyPolicy.ExportPolicy.Policies { + pconf.ApplyPolicy.ApplyPolicyConfig.ExportPolicy = append(pconf.ApplyPolicy.ApplyPolicyConfig.ExportPolicy, p.Name) + } + } + if a.ApplyPolicy.InPolicy != nil { + pconf.ApplyPolicy.ApplyPolicyConfig.DefaultInPolicy = config.DefaultPolicyType(a.ApplyPolicy.InPolicy.Default) + for _, p := range a.ApplyPolicy.InPolicy.Policies { + pconf.ApplyPolicy.ApplyPolicyConfig.InPolicy = append(pconf.ApplyPolicy.ApplyPolicyConfig.InPolicy, p.Name) + } + } + } + return pconf + } + configneigh := apitoConfig(arg.Peer) + peer := NewPeer(server.bgpConfig.Global, configneigh, loc) + server.setPolicyByConfig(peer, configneigh.ApplyPolicy) + if peer.isRouteServerClient() { + pathList := make([]*table.Path, 0) + rfList := peer.configuredRFlist() + for _, p := range server.neighborMap { + if p.isRouteServerClient() == true { + pathList = append(pathList, p.getAccepted(rfList)...) + } + } + pathList, _ = peer.ApplyPolicy(table.POLICY_DIRECTION_IMPORT, pathList) + if len(pathList) > 0 { + peer.localRib.ProcessPaths(pathList) + } + } + server.neighborMap[addr] = peer + peer.startFSMHandler(server.fsmincomingCh) + server.broadcastPeerState(peer) + case api.Operation_DEL: + SetTcpMD5SigSockopts(listener(net.ParseIP(addr)), addr, "") + log.Info("Delete a peer configuration for ", addr) + go func(addr string) { + t := time.AfterFunc(time.Minute*5, func() { log.Fatal("failed to free the fsm.h.t for ", addr) }) + n.fsm.h.t.Kill(nil) + n.fsm.h.t.Wait() + t.Stop() + t = time.AfterFunc(time.Minute*5, func() { log.Fatal("failed to free the fsm.h for ", addr) }) + n.fsm.t.Kill(nil) + n.fsm.t.Wait() + t.Stop() + }(addr) + m := server.dropPeerAllRoutes(n) + if len(m) > 0 { + sMsgs = append(sMsgs, m...) + } + delete(server.neighborMap, addr) + } + return sMsgs, err +} func (server *BgpServer) handleGrpcModDefinedSet(grpcReq *GrpcRequest) error { arg := grpcReq.Data.(*api.ModDefinedSetArguments) |