예제 #1
0
파일: fsm.go 프로젝트: jojimt/netplugin
func (h *FSMHandler) loop() error {
	fsm := h.fsm
	ch := make(chan bgp.FSMState)
	oldState := fsm.state

	f := func() error {
		nextState := bgp.FSMState(-1)
		var reason FsmStateReason
		switch fsm.state {
		case bgp.BGP_FSM_IDLE:
			nextState, reason = h.idle()
			// case bgp.BGP_FSM_CONNECT:
			// 	nextState = h.connect()
		case bgp.BGP_FSM_ACTIVE:
			nextState, reason = h.active()
		case bgp.BGP_FSM_OPENSENT:
			nextState, reason = h.opensent()
		case bgp.BGP_FSM_OPENCONFIRM:
			nextState, reason = h.openconfirm()
		case bgp.BGP_FSM_ESTABLISHED:
			nextState, reason = h.established()
		}
		fsm.reason = reason
		ch <- nextState
		return nil
	}

	h.t.Go(f)

	nextState := <-ch

	if nextState == bgp.BGP_FSM_ESTABLISHED && oldState == bgp.BGP_FSM_OPENCONFIRM {
		log.WithFields(log.Fields{
			"Topic": "Peer",
			"Key":   fsm.pConf.Config.NeighborAddress,
			"State": fsm.state.String(),
		}).Info("Peer Up")
	}

	if oldState == bgp.BGP_FSM_ESTABLISHED {
		// The main goroutine sent the notificaiton due to
		// deconfiguration or something.
		reason := fsm.reason
		if fsm.h.sentNotification != "" {
			reason = FsmStateReason(fmt.Sprintf("%s %s", FSM_NOTIFICATION_SENT, fsm.h.sentNotification))
		}
		log.WithFields(log.Fields{
			"Topic":  "Peer",
			"Key":    fsm.pConf.Config.NeighborAddress,
			"State":  fsm.state.String(),
			"Reason": reason,
		}).Info("Peer Down")
	}

	e := time.AfterFunc(time.Second*120, func() {
		log.WithFields(log.Fields{"Topic": "Peer"}).Fatalf("failed to free the fsm.h.t for %s %s %s", fsm.pConf.Config.NeighborAddress, oldState, nextState)
	})
	h.t.Wait()
	e.Stop()

	// under zero means that tomb.Dying()
	if nextState >= bgp.BGP_FSM_IDLE {
		e := &FsmMsg{
			MsgType: FSM_MSG_STATE_CHANGE,
			MsgSrc:  fsm.pConf.Config.NeighborAddress,
			MsgData: nextState,
			Version: h.fsm.version,
		}
		h.stateCh <- e
	}
	return nil
}
예제 #2
0
func (s *Server) GetNeighbor(ctx context.Context, arg *GetNeighborRequest) (*GetNeighborResponse, error) {
	toApi := func(pconf *config.Neighbor) *Peer {
		prefixLimits := make([]*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, &PrefixLimit{
					Family:               uint32(k),
					MaxPrefixes:          c.MaxPrefixes,
					ShutdownThresholdPct: uint32(c.ShutdownThresholdPct),
				})
			}
		}

		timer := pconf.Timers
		s := pconf.State
		localAddress := pconf.Transport.Config.LocalAddress
		if pconf.Transport.State.LocalAddress != "" {
			localAddress = pconf.Transport.State.LocalAddress
		}
		return &Peer{
			Conf: &PeerConf{
				NeighborAddress:   pconf.Config.NeighborAddress,
				Id:                s.RemoteRouterId,
				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,
				LocalAddress:      localAddress,
				NeighborInterface: pconf.Config.NeighborInterface,
			},
			Info: &PeerState{
				BgpState:   bgp.FSMState(s.SessionState.ToInt()).String(),
				AdminState: s.AdminState,
				Messages: &Messages{
					Received: &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: &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: &Timers{
				Config: &TimersConfig{
					ConnectRetry:      uint64(timer.Config.ConnectRetry),
					HoldTime:          uint64(timer.Config.HoldTime),
					KeepaliveInterval: uint64(timer.Config.KeepaliveInterval),
				},
				State: &TimersState{
					KeepaliveInterval:  uint64(timer.State.KeepaliveInterval),
					NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime),
					Uptime:             uint64(timer.State.Uptime),
					Downtime:           uint64(timer.State.Downtime),
				},
			},
			RouteReflector: &RouteReflector{
				RouteReflectorClient:    pconf.RouteReflector.Config.RouteReflectorClient,
				RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId),
			},
			RouteServer: &RouteServer{
				RouteServerClient: pconf.RouteServer.Config.RouteServerClient,
			},
		}
	}

	p := []*Peer{}
	for _, e := range s.bgpServer.GetNeighbor() {
		p = append(p, toApi(e))
	}
	return &GetNeighborResponse{Peers: p}, nil
}