github.com/osrg/gobgp@v2.0.0+incompatible/pkg/server/peer.go (about) 1 // Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package server 17 18 import ( 19 "fmt" 20 "net" 21 "time" 22 23 "github.com/osrg/gobgp/internal/pkg/config" 24 "github.com/osrg/gobgp/internal/pkg/table" 25 "github.com/osrg/gobgp/pkg/packet/bgp" 26 27 "github.com/eapache/channels" 28 log "github.com/sirupsen/logrus" 29 ) 30 31 const ( 32 flopThreshold = time.Second * 30 33 ) 34 35 var minConnectRetry = 10 36 37 type peerGroup struct { 38 Conf *config.PeerGroup 39 members map[string]config.Neighbor 40 dynamicNeighbors map[string]*config.DynamicNeighbor 41 } 42 43 func newPeerGroup(c *config.PeerGroup) *peerGroup { 44 return &peerGroup{ 45 Conf: c, 46 members: make(map[string]config.Neighbor), 47 dynamicNeighbors: make(map[string]*config.DynamicNeighbor), 48 } 49 } 50 51 func (pg *peerGroup) AddMember(c config.Neighbor) { 52 pg.members[c.State.NeighborAddress] = c 53 } 54 55 func (pg *peerGroup) DeleteMember(c config.Neighbor) { 56 delete(pg.members, c.State.NeighborAddress) 57 } 58 59 func (pg *peerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) { 60 pg.dynamicNeighbors[c.Config.Prefix] = c 61 } 62 63 func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *peer { 64 conf := config.Neighbor{ 65 Config: config.NeighborConfig{ 66 PeerGroup: pg.Config.PeerGroupName, 67 }, 68 State: config.NeighborState{ 69 NeighborAddress: neighborAddress, 70 }, 71 Transport: config.Transport{ 72 Config: config.TransportConfig{ 73 PassiveMode: true, 74 }, 75 }, 76 } 77 if err := config.OverwriteNeighborConfigWithPeerGroup(&conf, pg); err != nil { 78 log.WithFields(log.Fields{ 79 "Topic": "Peer", 80 "Key": neighborAddress, 81 }).Debugf("Can't overwrite neighbor config: %s", err) 82 return nil 83 } 84 if err := config.SetDefaultNeighborConfigValues(&conf, pg, g); err != nil { 85 log.WithFields(log.Fields{ 86 "Topic": "Peer", 87 "Key": neighborAddress, 88 }).Debugf("Can't set default config: %s", err) 89 return nil 90 } 91 peer := newPeer(g, &conf, loc, policy) 92 peer.fsm.lock.Lock() 93 peer.fsm.state = bgp.BGP_FSM_ACTIVE 94 peer.fsm.lock.Unlock() 95 return peer 96 } 97 98 type peer struct { 99 tableId string 100 fsm *fsm 101 adjRibIn *table.AdjRib 102 outgoing *channels.InfiniteChannel 103 policy *table.RoutingPolicy 104 localRib *table.TableManager 105 prefixLimitWarned map[bgp.RouteFamily]bool 106 llgrEndChs []chan struct{} 107 } 108 109 func newPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *peer { 110 peer := &peer{ 111 outgoing: channels.NewInfiniteChannel(), 112 localRib: loc, 113 policy: policy, 114 fsm: newFSM(g, conf, policy), 115 prefixLimitWarned: make(map[bgp.RouteFamily]bool), 116 } 117 if peer.isRouteServerClient() { 118 peer.tableId = conf.State.NeighborAddress 119 } else { 120 peer.tableId = table.GLOBAL_RIB_NAME 121 } 122 rfs, _ := config.AfiSafis(conf.AfiSafis).ToRfList() 123 peer.adjRibIn = table.NewAdjRib(rfs) 124 return peer 125 } 126 127 func (peer *peer) AS() uint32 { 128 peer.fsm.lock.RLock() 129 defer peer.fsm.lock.RUnlock() 130 return peer.fsm.pConf.State.PeerAs 131 } 132 133 func (peer *peer) ID() string { 134 peer.fsm.lock.RLock() 135 defer peer.fsm.lock.RUnlock() 136 return peer.fsm.pConf.State.NeighborAddress 137 } 138 139 func (peer *peer) TableID() string { 140 return peer.tableId 141 } 142 143 func (peer *peer) isIBGPPeer() bool { 144 peer.fsm.lock.RLock() 145 defer peer.fsm.lock.RUnlock() 146 return peer.fsm.pConf.State.PeerType == config.PEER_TYPE_INTERNAL 147 } 148 149 func (peer *peer) isRouteServerClient() bool { 150 peer.fsm.lock.RLock() 151 defer peer.fsm.lock.RUnlock() 152 return peer.fsm.pConf.RouteServer.Config.RouteServerClient 153 } 154 155 func (peer *peer) isRouteReflectorClient() bool { 156 peer.fsm.lock.RLock() 157 defer peer.fsm.lock.RUnlock() 158 return peer.fsm.pConf.RouteReflector.Config.RouteReflectorClient 159 } 160 161 func (peer *peer) isGracefulRestartEnabled() bool { 162 peer.fsm.lock.RLock() 163 defer peer.fsm.lock.RUnlock() 164 return peer.fsm.pConf.GracefulRestart.State.Enabled 165 } 166 167 func (peer *peer) getAddPathMode(family bgp.RouteFamily) bgp.BGPAddPathMode { 168 peer.fsm.lock.RLock() 169 defer peer.fsm.lock.RUnlock() 170 if mode, y := peer.fsm.rfMap[family]; y { 171 return mode 172 } 173 return bgp.BGP_ADD_PATH_NONE 174 } 175 176 func (peer *peer) isAddPathReceiveEnabled(family bgp.RouteFamily) bool { 177 return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_RECEIVE) > 0 178 } 179 180 func (peer *peer) isAddPathSendEnabled(family bgp.RouteFamily) bool { 181 return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_SEND) > 0 182 } 183 184 func (peer *peer) isDynamicNeighbor() bool { 185 peer.fsm.lock.RLock() 186 defer peer.fsm.lock.RUnlock() 187 return peer.fsm.pConf.Config.NeighborAddress == "" && peer.fsm.pConf.Config.NeighborInterface == "" 188 } 189 190 func (peer *peer) recvedAllEOR() bool { 191 peer.fsm.lock.RLock() 192 defer peer.fsm.lock.RUnlock() 193 for _, a := range peer.fsm.pConf.AfiSafis { 194 if s := a.MpGracefulRestart.State; s.Enabled && !s.EndOfRibReceived { 195 return false 196 } 197 } 198 return true 199 } 200 201 func (peer *peer) configuredRFlist() []bgp.RouteFamily { 202 peer.fsm.lock.RLock() 203 defer peer.fsm.lock.RUnlock() 204 rfs, _ := config.AfiSafis(peer.fsm.pConf.AfiSafis).ToRfList() 205 return rfs 206 } 207 208 func (peer *peer) negotiatedRFList() []bgp.RouteFamily { 209 peer.fsm.lock.RLock() 210 defer peer.fsm.lock.RUnlock() 211 l := make([]bgp.RouteFamily, 0, len(peer.fsm.rfMap)) 212 for family := range peer.fsm.rfMap { 213 l = append(l, family) 214 } 215 return l 216 } 217 218 func (peer *peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily { 219 id := peer.ID() 220 peer.fsm.lock.RLock() 221 defer peer.fsm.lock.RUnlock() 222 if peer.fsm.pConf.Config.Vrf != "" { 223 fs := make([]bgp.RouteFamily, 0, len(families)) 224 for _, f := range families { 225 switch f { 226 case bgp.RF_IPv4_UC: 227 fs = append(fs, bgp.RF_IPv4_VPN) 228 case bgp.RF_IPv6_UC: 229 fs = append(fs, bgp.RF_IPv6_VPN) 230 default: 231 log.WithFields(log.Fields{ 232 "Topic": "Peer", 233 "Key": id, 234 "Family": f, 235 "VRF": peer.fsm.pConf.Config.Vrf, 236 }).Warn("invalid family configured for neighbor with vrf") 237 } 238 } 239 families = fs 240 } 241 return families 242 } 243 244 func classifyFamilies(all, part []bgp.RouteFamily) ([]bgp.RouteFamily, []bgp.RouteFamily) { 245 a := []bgp.RouteFamily{} 246 b := []bgp.RouteFamily{} 247 for _, f := range all { 248 p := true 249 for _, g := range part { 250 if f == g { 251 p = false 252 a = append(a, f) 253 break 254 } 255 } 256 if p { 257 b = append(b, f) 258 } 259 } 260 return a, b 261 } 262 263 func (peer *peer) forwardingPreservedFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) { 264 peer.fsm.lock.RLock() 265 list := []bgp.RouteFamily{} 266 for _, a := range peer.fsm.pConf.AfiSafis { 267 if s := a.MpGracefulRestart.State; s.Enabled && s.Received { 268 list = append(list, a.State.Family) 269 } 270 } 271 peer.fsm.lock.RUnlock() 272 return classifyFamilies(peer.configuredRFlist(), list) 273 } 274 275 func (peer *peer) llgrFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) { 276 peer.fsm.lock.RLock() 277 list := []bgp.RouteFamily{} 278 for _, a := range peer.fsm.pConf.AfiSafis { 279 if a.LongLivedGracefulRestart.State.Enabled { 280 list = append(list, a.State.Family) 281 } 282 } 283 peer.fsm.lock.RUnlock() 284 return classifyFamilies(peer.configuredRFlist(), list) 285 } 286 287 func (peer *peer) isLLGREnabledFamily(family bgp.RouteFamily) bool { 288 peer.fsm.lock.RLock() 289 llgrEnabled := peer.fsm.pConf.GracefulRestart.Config.LongLivedEnabled 290 peer.fsm.lock.RUnlock() 291 if !llgrEnabled { 292 return false 293 } 294 fs, _ := peer.llgrFamilies() 295 for _, f := range fs { 296 if f == family { 297 return true 298 } 299 } 300 return false 301 } 302 303 func (peer *peer) llgrRestartTime(family bgp.RouteFamily) uint32 { 304 peer.fsm.lock.RLock() 305 defer peer.fsm.lock.RUnlock() 306 for _, a := range peer.fsm.pConf.AfiSafis { 307 if a.State.Family == family { 308 return a.LongLivedGracefulRestart.State.PeerRestartTime 309 } 310 } 311 return 0 312 } 313 314 func (peer *peer) llgrRestartTimerExpired(family bgp.RouteFamily) bool { 315 peer.fsm.lock.RLock() 316 defer peer.fsm.lock.RUnlock() 317 all := true 318 for _, a := range peer.fsm.pConf.AfiSafis { 319 if a.State.Family == family { 320 a.LongLivedGracefulRestart.State.PeerRestartTimerExpired = true 321 } 322 s := a.LongLivedGracefulRestart.State 323 if s.Received && !s.PeerRestartTimerExpired { 324 all = false 325 } 326 } 327 return all 328 } 329 330 func (peer *peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path { 331 paths := peer.adjRibIn.PathList(fs, true) 332 for i, p := range paths { 333 doStale := true 334 for _, c := range p.GetCommunities() { 335 if c == uint32(bgp.COMMUNITY_NO_LLGR) { 336 doStale = false 337 p = p.Clone(true) 338 break 339 } 340 } 341 if doStale { 342 p = p.Clone(false) 343 p.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false) 344 } 345 paths[i] = p 346 } 347 return paths 348 } 349 350 func (peer *peer) stopPeerRestarting() { 351 peer.fsm.lock.Lock() 352 defer peer.fsm.lock.Unlock() 353 peer.fsm.pConf.GracefulRestart.State.PeerRestarting = false 354 for _, ch := range peer.llgrEndChs { 355 close(ch) 356 } 357 peer.llgrEndChs = make([]chan struct{}, 0) 358 359 } 360 361 func (peer *peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path { 362 if peer.ID() != path.GetSource().Address.String() { 363 return path 364 } 365 366 // Note: Multiple paths having the same prefix could exist the withdrawals 367 // list in the case of Route Server setup with import policies modifying 368 // paths. In such case, gobgp sends duplicated update messages; withdraw 369 // messages for the same prefix. 370 if !peer.isRouteServerClient() { 371 if peer.isRouteReflectorClient() && path.GetRouteFamily() == bgp.RF_RTC_UC { 372 // When the peer is a Route Reflector client and the given path 373 // contains the Route Tartget Membership NLRI, the path should not 374 // be withdrawn in order to signal the client to distribute routes 375 // with the specific RT to Route Reflector. 376 return path 377 } else if !path.IsWithdraw && old != nil && old.GetSource().Address.String() != peer.ID() { 378 // Say, peer A and B advertized same prefix P, and best path 379 // calculation chose a path from B as best. When B withdraws prefix 380 // P, best path calculation chooses the path from A as best. For 381 // peers other than A, this path should be advertised (as implicit 382 // withdrawal). However for A, we should advertise the withdrawal 383 // path. Thing is same when peer A and we advertized prefix P (as 384 // local route), then, we withdraws the prefix. 385 return old.Clone(true) 386 } 387 } 388 log.WithFields(log.Fields{ 389 "Topic": "Peer", 390 "Key": peer.ID(), 391 "Data": path, 392 }).Debug("From me, ignore.") 393 return nil 394 } 395 396 func (peer *peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage { 397 if maxPrefixes := int(c.MaxPrefixes); maxPrefixes > 0 { 398 count := peer.adjRibIn.Count([]bgp.RouteFamily{k}) 399 pct := int(c.ShutdownThresholdPct) 400 if pct > 0 && !peer.prefixLimitWarned[k] && count > (maxPrefixes*pct/100) { 401 peer.prefixLimitWarned[k] = true 402 log.WithFields(log.Fields{ 403 "Topic": "Peer", 404 "Key": peer.ID(), 405 "AddressFamily": k.String(), 406 }).Warnf("prefix limit %d%% reached", pct) 407 } 408 if count > maxPrefixes { 409 log.WithFields(log.Fields{ 410 "Topic": "Peer", 411 "Key": peer.ID(), 412 "AddressFamily": k.String(), 413 }).Warnf("prefix limit reached") 414 return bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_MAXIMUM_NUMBER_OF_PREFIXES_REACHED, nil) 415 } 416 } 417 return nil 418 419 } 420 421 func (peer *peer) updatePrefixLimitConfig(c []config.AfiSafi) error { 422 peer.fsm.lock.RLock() 423 x := peer.fsm.pConf.AfiSafis 424 peer.fsm.lock.RUnlock() 425 y := c 426 if len(x) != len(y) { 427 return fmt.Errorf("changing supported afi-safi is not allowed") 428 } 429 m := make(map[bgp.RouteFamily]config.PrefixLimitConfig) 430 for _, e := range x { 431 m[e.State.Family] = e.PrefixLimit.Config 432 } 433 for _, e := range y { 434 if p, ok := m[e.State.Family]; !ok { 435 return fmt.Errorf("changing supported afi-safi is not allowed") 436 } else if !p.Equal(&e.PrefixLimit.Config) { 437 log.WithFields(log.Fields{ 438 "Topic": "Peer", 439 "Key": peer.ID(), 440 "AddressFamily": e.Config.AfiSafiName, 441 "OldMaxPrefixes": p.MaxPrefixes, 442 "NewMaxPrefixes": e.PrefixLimit.Config.MaxPrefixes, 443 "OldShutdownThresholdPct": p.ShutdownThresholdPct, 444 "NewShutdownThresholdPct": e.PrefixLimit.Config.ShutdownThresholdPct, 445 }).Warnf("update prefix limit configuration") 446 peer.prefixLimitWarned[e.State.Family] = false 447 if msg := peer.doPrefixLimit(e.State.Family, &e.PrefixLimit.Config); msg != nil { 448 sendfsmOutgoingMsg(peer, nil, msg, true) 449 } 450 } 451 } 452 peer.fsm.lock.Lock() 453 peer.fsm.pConf.AfiSafis = c 454 peer.fsm.lock.Unlock() 455 return nil 456 } 457 458 func (peer *peer) handleUpdate(e *fsmMsg) ([]*table.Path, []bgp.RouteFamily, *bgp.BGPMessage) { 459 m := e.MsgData.(*bgp.BGPMessage) 460 update := m.Body.(*bgp.BGPUpdate) 461 log.WithFields(log.Fields{ 462 "Topic": "Peer", 463 "Key": peer.fsm.pConf.State.NeighborAddress, 464 "nlri": update.NLRI, 465 "withdrawals": update.WithdrawnRoutes, 466 "attributes": update.PathAttributes, 467 }).Debug("received update") 468 peer.fsm.lock.Lock() 469 peer.fsm.pConf.Timers.State.UpdateRecvTime = time.Now().Unix() 470 peer.fsm.lock.Unlock() 471 if len(e.PathList) > 0 { 472 paths := make([]*table.Path, 0, len(e.PathList)) 473 eor := []bgp.RouteFamily{} 474 for _, path := range e.PathList { 475 if path.IsEOR() { 476 family := path.GetRouteFamily() 477 log.WithFields(log.Fields{ 478 "Topic": "Peer", 479 "Key": peer.ID(), 480 "AddressFamily": family, 481 }).Debug("EOR received") 482 eor = append(eor, family) 483 continue 484 } 485 // RFC4271 9.1.2 Phase 2: Route Selection 486 // 487 // If the AS_PATH attribute of a BGP route contains an AS loop, the BGP 488 // route should be excluded from the Phase 2 decision function. 489 if aspath := path.GetAsPath(); aspath != nil { 490 peer.fsm.lock.RLock() 491 localAS := peer.fsm.peerInfo.LocalAS 492 allowOwnAS := int(peer.fsm.pConf.AsPathOptions.Config.AllowOwnAs) 493 peer.fsm.lock.RUnlock() 494 if hasOwnASLoop(localAS, allowOwnAS, aspath) { 495 path.SetAsLooped(true) 496 continue 497 } 498 } 499 // RFC4456 8. Avoiding Routing Information Loops 500 // A router that recognizes the ORIGINATOR_ID attribute SHOULD 501 // ignore a route received with its BGP Identifier as the ORIGINATOR_ID. 502 isIBGPPeer := peer.isIBGPPeer() 503 peer.fsm.lock.RLock() 504 routerId := peer.fsm.gConf.Config.RouterId 505 peer.fsm.lock.RUnlock() 506 if isIBGPPeer { 507 if id := path.GetOriginatorID(); routerId == id.String() { 508 log.WithFields(log.Fields{ 509 "Topic": "Peer", 510 "Key": peer.ID(), 511 "OriginatorID": id, 512 "Data": path, 513 }).Debug("Originator ID is mine, ignore") 514 continue 515 } 516 } 517 paths = append(paths, path) 518 } 519 peer.adjRibIn.Update(e.PathList) 520 peer.fsm.lock.RLock() 521 peerAfiSafis := peer.fsm.pConf.AfiSafis 522 peer.fsm.lock.RUnlock() 523 for _, af := range peerAfiSafis { 524 if msg := peer.doPrefixLimit(af.State.Family, &af.PrefixLimit.Config); msg != nil { 525 return nil, nil, msg 526 } 527 } 528 return paths, eor, nil 529 } 530 return nil, nil, nil 531 } 532 533 func (peer *peer) startFSMHandler(incoming *channels.InfiniteChannel, stateCh chan *fsmMsg) { 534 handler := newFSMHandler(peer.fsm, incoming, stateCh, peer.outgoing) 535 peer.fsm.lock.Lock() 536 peer.fsm.h = handler 537 peer.fsm.lock.Unlock() 538 } 539 540 func (peer *peer) StaleAll(rfList []bgp.RouteFamily) []*table.Path { 541 return peer.adjRibIn.StaleAll(rfList) 542 } 543 544 func (peer *peer) PassConn(conn *net.TCPConn) { 545 select { 546 case peer.fsm.connCh <- conn: 547 default: 548 conn.Close() 549 log.WithFields(log.Fields{ 550 "Topic": "Peer", 551 "Key": peer.ID(), 552 }).Warn("accepted conn is closed to avoid be blocked") 553 } 554 } 555 556 func (peer *peer) DropAll(rfList []bgp.RouteFamily) { 557 peer.adjRibIn.Drop(rfList) 558 } 559 560 func (peer *peer) stopFSM() error { 561 failed := false 562 peer.fsm.lock.RLock() 563 addr := peer.fsm.pConf.State.NeighborAddress 564 state := peer.fsm.state 565 peer.fsm.lock.RUnlock() 566 t1 := time.AfterFunc(time.Minute*5, func() { 567 log.WithFields(log.Fields{ 568 "Topic": "Peer", 569 }).Warnf("Failed to free the fsm.h.t for %s", addr) 570 failed = true 571 }) 572 peer.fsm.h.ctxCancel() 573 peer.fsm.h.wg.Wait() 574 t1.Stop() 575 if !failed { 576 log.WithFields(log.Fields{ 577 "Topic": "Peer", 578 "Key": addr, 579 "State": state, 580 }).Debug("freed fsm.h.t") 581 cleanInfiniteChannel(peer.outgoing) 582 } 583 return fmt.Errorf("Failed to free FSM for %s", addr) 584 }