diff options
Diffstat (limited to 'server/peer.go')
-rw-r--r-- | server/peer.go | 176 |
1 files changed, 59 insertions, 117 deletions
diff --git a/server/peer.go b/server/peer.go index 8f43299e..1844236e 100644 --- a/server/peer.go +++ b/server/peer.go @@ -32,35 +32,41 @@ const ( ) type Peer struct { - gConf config.Global - conf config.Neighbor - fsm *FSM - rfMap map[bgp.RouteFamily]bool - capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface - adjRibIn *table.AdjRib - adjRibOut *table.AdjRib - outgoing chan *bgp.BGPMessage - inPolicies []*table.Policy - defaultInPolicy table.RouteType - recvOpen *bgp.BGPMessage - localRib *table.TableManager + tableId string + gConf config.Global + conf config.Neighbor + fsm *FSM + rfMap map[bgp.RouteFamily]bool + capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface + adjRibIn *table.AdjRib + adjRibOut *table.AdjRib + outgoing chan *bgp.BGPMessage + recvOpen *bgp.BGPMessage + policy *table.RoutingPolicy + localRib *table.TableManager } -func NewPeer(g config.Global, conf config.Neighbor, loc *table.TableManager) *Peer { - rfs, _ := conf.AfiSafis.ToRfList() +func NewPeer(g config.Global, conf config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *Peer { peer := &Peer{ - gConf: g, - conf: conf, - rfMap: make(map[bgp.RouteFamily]bool), - capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface), - outgoing: make(chan *bgp.BGPMessage, 128), - adjRibIn: table.NewAdjRib(rfs), - adjRibOut: table.NewAdjRib(rfs), - localRib: loc, + gConf: g, + conf: conf, + rfMap: make(map[bgp.RouteFamily]bool), + capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface), + outgoing: make(chan *bgp.BGPMessage, 128), + localRib: loc, + policy: policy, + } + tableId := table.GLOBAL_RIB_NAME + if peer.isRouteServerClient() { + tableId = conf.NeighborConfig.NeighborAddress.String() } + peer.tableId = tableId conf.NeighborState.SessionState = uint32(bgp.BGP_FSM_IDLE) conf.Timers.TimersState.Downtime = time.Now().Unix() - peer.fsm = NewFSM(&g, &conf, peer) + rfs, _ := conf.AfiSafis.ToRfList() + peer.adjRibIn = table.NewAdjRib(peer.ID(), rfs) + peer.adjRibOut = table.NewAdjRib(peer.ID(), rfs) + peer.fsm = NewFSM(&g, &conf, policy) return peer } @@ -72,6 +78,14 @@ func (peer *Peer) Outgoing() chan *bgp.BGPMessage { return peer.outgoing } +func (peer *Peer) ID() string { + return peer.conf.NeighborConfig.NeighborAddress.String() +} + +func (peer *Peer) TableID() string { + return peer.tableId +} + func (peer *Peer) isIBGPPeer() bool { return peer.conf.NeighborConfig.PeerAs == peer.gConf.GlobalConfig.As } @@ -94,11 +108,18 @@ func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path { } func (peer *Peer) getBestFromLocal(rfList []bgp.RouteFamily) ([]*table.Path, []*table.Path) { - pathList, filtered := peer.ApplyPolicy(table.POLICY_DIRECTION_EXPORT, filterpath(peer, peer.localRib.GetBestPathList(rfList))) - if peer.isRouteServerClient() == false { - for _, path := range pathList { - path.UpdatePathAttrs(&peer.gConf, &peer.conf) + pathList := []*table.Path{} + filtered := []*table.Path{} + for _, path := range peer.localRib.GetBestPathList(peer.TableID(), rfList) { + p := peer.policy.ApplyPolicy(peer.TableID(), table.POLICY_DIRECTION_EXPORT, filterpath(peer, path)) + if p == nil { + filtered = append(filtered, path) + continue + } + if !peer.isRouteServerClient() { + p.UpdatePathAttrs(&peer.gConf, &peer.conf) } + pathList = append(pathList, p) } return pathList, filtered } @@ -132,16 +153,13 @@ func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode] return capMap, rfMap } -func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, bool, []*bgp.BGPMessage) { +func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, []*bgp.BGPMessage) { m := e.MsgData.(*bgp.BGPMessage) - bgpMsgList := []*bgp.BGPMessage{} - pathList := []*table.Path{} log.WithFields(log.Fields{ "Topic": "Peer", "Key": peer.conf.NeighborConfig.NeighborAddress, "data": m, }).Debug("received") - update := false switch m.Header.Type { case bgp.BGP_MSG_OPEN: @@ -178,11 +196,11 @@ func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, bool, []*bgp.BGPMe peer.adjRibOut.Drop(rfList) accepted, filtered := peer.getBestFromLocal(rfList) peer.adjRibOut.Update(accepted) - pathList = append(pathList, accepted...) for _, path := range filtered { path.IsWithdraw = true - pathList = append(pathList, path) + accepted = append(accepted, path) } + return nil, table.CreateUpdateMsgFromPaths(accepted) } else { log.WithFields(log.Fields{ "Topic": "Peer", @@ -191,11 +209,16 @@ func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, bool, []*bgp.BGPMe } case bgp.BGP_MSG_UPDATE: - update = true peer.conf.Timers.TimersState.UpdateRecvTime = time.Now().Unix() if len(e.PathList) > 0 { peer.adjRibIn.Update(e.PathList) - pathList = e.PathList + paths := make([]*table.Path, 0, len(e.PathList)) + for _, path := range e.PathList { + if path.Filtered(peer.TableID()) != table.POLICY_DIRECTION_IN { + paths = append(paths, path) + } + } + return paths, nil } case bgp.BGP_MSG_NOTIFICATION: body := m.Body.(*bgp.BGPNotification) @@ -207,7 +230,7 @@ func (peer *Peer) handleBGPmessage(e *FsmMsg) ([]*table.Path, bool, []*bgp.BGPMe "Data": body.Data, }).Warn("received notification") } - return pathList, update, bgpMsgList + return nil, nil } func (peer *Peer) startFSMHandler(incoming chan *FsmMsg) { @@ -351,87 +374,6 @@ func (peer *Peer) ToApiStruct() *api.Peer { } } -func (peer *Peer) GetPolicy(d table.PolicyDirection) []*table.Policy { - switch d { - case table.POLICY_DIRECTION_IN: - return peer.inPolicies - default: - return peer.localRib.GetPolicy(d) - } - return nil -} - -func (peer *Peer) SetPolicy(d table.PolicyDirection, policies []*table.Policy) error { - switch d { - case table.POLICY_DIRECTION_IN: - peer.inPolicies = policies - default: - return peer.localRib.SetPolicy(d, policies) - } - return nil -} - -func (peer *Peer) GetDefaultPolicy(d table.PolicyDirection) table.RouteType { - switch d { - case table.POLICY_DIRECTION_IN: - return peer.defaultInPolicy - default: - return peer.localRib.GetDefaultPolicy(d) - } - return table.ROUTE_TYPE_NONE -} - -func (peer *Peer) SetDefaultPolicy(d table.PolicyDirection, typ table.RouteType) error { - switch d { - case table.POLICY_DIRECTION_IN: - peer.defaultInPolicy = typ - default: - if peer.isRouteServerClient() { - return peer.localRib.SetDefaultPolicy(d, typ) - } - } - return nil -} - -func (peer *Peer) ApplyPolicy(d table.PolicyDirection, paths []*table.Path) ([]*table.Path, []*table.Path) { - newpaths := make([]*table.Path, 0, len(paths)) - filteredPaths := make([]*table.Path, 0) - for _, path := range paths { - result := table.ROUTE_TYPE_NONE - newpath := path - for _, p := range peer.GetPolicy(d) { - result, newpath = p.Apply(path) - if result != table.ROUTE_TYPE_NONE { - break - } - } - - if result == table.ROUTE_TYPE_NONE { - result = peer.GetDefaultPolicy(d) - } - - switch result { - case table.ROUTE_TYPE_ACCEPT: - if d == table.POLICY_DIRECTION_IN { - path.Filtered = false - } - newpaths = append(newpaths, newpath) - case table.ROUTE_TYPE_REJECT: - if d == table.POLICY_DIRECTION_IN { - path.Filtered = true - } - filteredPaths = append(filteredPaths, path) - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.conf.NeighborConfig.NeighborAddress, - "Path": path, - "Direction": d, - }).Debug("reject") - } - } - return newpaths, filteredPaths -} - func (peer *Peer) DropAll(rfList []bgp.RouteFamily) { peer.adjRibIn.Drop(rfList) peer.adjRibOut.Drop(rfList) |