diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2017-07-04 14:24:57 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-07-04 14:24:57 +0900 |
commit | 454fd93ef707c530b3ece04ef4727ad1f7371d4b (patch) | |
tree | 379ef72e0b04fcc5bb913c435f162bdeaf5fcbdc /server | |
parent | 1d46f58ff1df4d1195091a9f25e74a583801b39d (diff) |
support addpath recv
Diffstat (limited to 'server')
-rw-r--r-- | server/fsm.go | 87 | ||||
-rw-r--r-- | server/server.go | 8 | ||||
-rw-r--r-- | server/server_test.go | 2 |
3 files changed, 74 insertions, 23 deletions
diff --git a/server/fsm.go b/server/fsm.go index afd04b3e..953e2f7d 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -124,7 +124,7 @@ type FSM struct { adminStateCh chan AdminStateOperation getActiveCh chan struct{} h *FSMHandler - rfMap map[bgp.RouteFamily]bool + rfMap map[bgp.RouteFamily]bgp.BGPAddPathMode capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface recvOpen *bgp.BGPMessage peerInfo *table.PeerInfo @@ -132,6 +132,7 @@ type FSM struct { gracefulRestartTimer *time.Timer twoByteAsTrans bool version uint + marshallingOptions *bgp.MarshallingOption } func (fsm *FSM) bgpMessageStateUpdate(MessageType uint8, isIn bool) { @@ -212,7 +213,7 @@ func NewFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingP adminState: adminState, adminStateCh: make(chan AdminStateOperation, 1), getActiveCh: make(chan struct{}), - rfMap: make(map[bgp.RouteFamily]bool), + rfMap: make(map[bgp.RouteFamily]bgp.BGPAddPathMode), capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface), peerInfo: table.NewPeerInfo(gConf, pConf), policy: policy, @@ -614,6 +615,23 @@ func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInt cap := bgp.NewCapExtendedNexthop(tuples) caps = append(caps, cap) } + + var mode bgp.BGPAddPathMode + if pConf.AddPaths.Config.Receive { + mode |= bgp.BGP_ADD_PATH_RECEIVE + } + if pConf.AddPaths.Config.SendMax > 0 { + mode |= bgp.BGP_ADD_PATH_SEND + } + if uint8(mode) > 0 { + items := make([]*bgp.CapAddPathTuple, 0, len(pConf.AfiSafis)) + for _, rf := range pConf.AfiSafis { + k, _ := bgp.GetRouteFamily(string(rf.Config.AfiSafiName)) + items = append(items, bgp.NewCapAddPathTuple(k, mode)) + } + caps = append(caps, bgp.NewCapAddPath(items)) + } + return caps } @@ -703,7 +721,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { } now := time.Now() - m, err := bgp.ParseBGPBody(hd, bodyBuf) + m, err := bgp.ParseBGPBody(hd, bodyBuf, h.fsm.marshallingOptions) if err == nil { h.fsm.bgpMessageStateUpdate(m.Header.Type, true) err = bgp.ValidateBGPMessage(m) @@ -841,10 +859,8 @@ func (h *FSMHandler) recvMessage() error { return nil } -func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface, map[bgp.RouteFamily]bool) { +func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface, map[bgp.RouteFamily]bgp.BGPAddPathMode) { capMap := make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface) - rfMap := config.CreateRfMap(n) - r := make(map[bgp.RouteFamily]bool) for _, p := range open.OptParams { if paramCap, y := p.(*bgp.OptionParameterCapability); y { for _, c := range paramCap.Capability { @@ -853,26 +869,53 @@ func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode] m = make([]bgp.ParameterCapabilityInterface, 0, 1) } capMap[c.Code()] = append(m, c) + } + } + } - if c.Code() == bgp.BGP_CAP_MULTIPROTOCOL { - m := c.(*bgp.CapMultiProtocol) - r[m.CapValue] = true - } + // squash add path cap + if caps, y := capMap[bgp.BGP_CAP_ADD_PATH]; y { + items := make([]*bgp.CapAddPathTuple, 0, len(caps)) + for _, c := range caps { + for _, i := range c.(*bgp.CapAddPath).Tuples { + items = append(items, i) } } + capMap[bgp.BGP_CAP_ADD_PATH] = []bgp.ParameterCapabilityInterface{bgp.NewCapAddPath(items)} } - if len(r) > 0 { - for rf, _ := range rfMap { - if _, y := r[rf]; !y { - delete(rfMap, rf) + // remote open message may not include multi-protocol capability + if _, y := capMap[bgp.BGP_CAP_MULTIPROTOCOL]; !y { + capMap[bgp.BGP_CAP_MULTIPROTOCOL] = []bgp.ParameterCapabilityInterface{bgp.NewCapMultiProtocol(bgp.RF_IPv4_UC)} + } + + local := config.CreateRfMap(n) + remote := make(map[bgp.RouteFamily]bgp.BGPAddPathMode) + for _, c := range capMap[bgp.BGP_CAP_MULTIPROTOCOL] { + family := c.(*bgp.CapMultiProtocol).CapValue + remote[family] = bgp.BGP_ADD_PATH_NONE + for _, a := range capMap[bgp.BGP_CAP_ADD_PATH] { + for _, i := range a.(*bgp.CapAddPath).Tuples { + if i.RouteFamily == family { + remote[family] = i.Mode + } } } - } else { - rfMap = make(map[bgp.RouteFamily]bool) - rfMap[bgp.RF_IPv4_UC] = true } - return capMap, rfMap + negotiated := make(map[bgp.RouteFamily]bgp.BGPAddPathMode) + for family, mode := range local { + if m, y := remote[family]; y { + n := bgp.BGP_ADD_PATH_NONE + if mode&bgp.BGP_ADD_PATH_SEND > 0 && m&bgp.BGP_ADD_PATH_RECEIVE > 0 { + n |= bgp.BGP_ADD_PATH_SEND + } + if mode&bgp.BGP_ADD_PATH_RECEIVE > 0 && m&bgp.BGP_ADD_PATH_SEND > 0 { + n |= bgp.BGP_ADD_PATH_RECEIVE + } + negotiated[family] = n + } + } + return capMap, negotiated } func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { @@ -955,6 +998,12 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { fsm.peerInfo.ID = body.ID fsm.capMap, fsm.rfMap = open2Cap(body, fsm.pConf) + if _, y := fsm.capMap[bgp.BGP_CAP_ADD_PATH]; y { + fsm.marshallingOptions = &bgp.MarshallingOption{ + AddPath: fsm.rfMap, + } + } + // calculate HoldTime // RFC 4271 P.13 // a BGP speaker MUST calculate the value of the Hold Timer @@ -1202,7 +1251,7 @@ func (h *FSMHandler) sendMessageloop() error { table.UpdatePathAttrs2ByteAs(m.Body.(*bgp.BGPUpdate)) table.UpdatePathAggregator2ByteAs(m.Body.(*bgp.BGPUpdate)) } - b, err := m.Serialize() + b, err := m.Serialize(h.fsm.marshallingOptions) if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", diff --git a/server/server.go b/server/server.go index b821ea82..bbbfb524 100644 --- a/server/server.go +++ b/server/server.go @@ -346,7 +346,7 @@ func filterpath(peer *Peer, path, old *table.Path) *table.Path { if peer.isIBGPPeer() { ignore := false //RFC4684 Constrained Route Distribution - if peer.fsm.rfMap[bgp.RF_RTC_UC] && path.GetRouteFamily() != bgp.RF_RTC_UC { + if _, y := peer.fsm.rfMap[bgp.RF_RTC_UC]; y && path.GetRouteFamily() != bgp.RF_RTC_UC { ignore = true for _, ext := range path.GetExtCommunities() { for _, path := range peer.adjRibIn.PathList([]bgp.RouteFamily{bgp.RF_RTC_UC}, true) { @@ -870,7 +870,8 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { // waiting sending non-route-target NLRIs since the peer won't send // any routes (and EORs) before we send ours (or deferral-timer expires). var pathList []*table.Path - if c := config.GetAfiSafi(peer.fsm.pConf, bgp.RF_RTC_UC); !peer.fsm.pConf.GracefulRestart.State.PeerRestarting && peer.fsm.rfMap[bgp.RF_RTC_UC] && c.RouteTargetMembership.Config.DeferralTime > 0 { + _, y := peer.fsm.rfMap[bgp.RF_RTC_UC] + if c := config.GetAfiSafi(peer.fsm.pConf, bgp.RF_RTC_UC); y && !peer.fsm.pConf.GracefulRestart.State.PeerRestarting && c.RouteTargetMembership.Config.DeferralTime > 0 { pathList, _ = peer.getBestFromLocal([]bgp.RouteFamily{bgp.RF_RTC_UC}) t := c.RouteTargetMembership.Config.DeferralTime for _, f := range peer.configuredRFlist() { @@ -1456,6 +1457,7 @@ func (s *BgpServer) softResetOut(addr string, family bgp.RouteFamily, deferral b } if deferral { + _, y := peer.fsm.rfMap[bgp.RF_RTC_UC] if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { peer.fsm.pConf.GracefulRestart.State.LocalRestarting = false log.WithFields(log.Fields{ @@ -1463,7 +1465,7 @@ func (s *BgpServer) softResetOut(addr string, family bgp.RouteFamily, deferral b "Key": peer.ID(), "Families": families, }).Debug("deferral timer expired") - } else if c := config.GetAfiSafi(peer.fsm.pConf, bgp.RF_RTC_UC); peer.fsm.rfMap[bgp.RF_RTC_UC] && !c.MpGracefulRestart.State.EndOfRibReceived { + } else if c := config.GetAfiSafi(peer.fsm.pConf, bgp.RF_RTC_UC); y && !c.MpGracefulRestart.State.EndOfRibReceived { log.WithFields(log.Fields{ "Topic": "Peer", "Key": peer.ID(), diff --git a/server/server_test.go b/server/server_test.go index fb7b97f3..b8dc58f5 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -209,7 +209,7 @@ func newPeerandInfo(myAs, as uint32, address string, rib *table.TableManager) (* rib, policy) for _, f := range rib.GetRFlist() { - p.fsm.rfMap[f] = true + p.fsm.rfMap[f] = bgp.BGP_ADD_PATH_NONE } return p, &table.PeerInfo{AS: as, Address: net.ParseIP(address)} } |