github.com/osrg/gobgp@v2.0.0+incompatible/pkg/server/fsm.go (about) 1 // Copyright (C) 2014 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 "context" 20 "fmt" 21 "io" 22 "math/rand" 23 "net" 24 "strconv" 25 "sync" 26 "syscall" 27 "time" 28 29 "github.com/eapache/channels" 30 "github.com/osrg/gobgp/internal/pkg/config" 31 "github.com/osrg/gobgp/internal/pkg/table" 32 "github.com/osrg/gobgp/pkg/packet/bgp" 33 "github.com/osrg/gobgp/pkg/packet/bmp" 34 35 log "github.com/sirupsen/logrus" 36 ) 37 38 type peerDownReason int 39 40 const ( 41 peerDownByLocal peerDownReason = iota 42 peerDownByLocalWithoutNotification 43 peerDownByRemote 44 peerDownByRemoteWithoutNotification 45 ) 46 47 type fsmStateReasonType uint8 48 49 const ( 50 fsmDying fsmStateReasonType = iota 51 fsmAdminDown 52 fsmReadFailed 53 fsmWriteFailed 54 fsmNotificationSent 55 fsmNotificationRecv 56 fsmHoldTimerExpired 57 fsmIdleTimerExpired 58 fsmRestartTimerExpired 59 fsmGracefulRestart 60 fsmInvalidMsg 61 fsmNewConnection 62 fsmOpenMsgReceived 63 fsmOpenMsgNegotiated 64 fsmHardReset 65 ) 66 67 type fsmStateReason struct { 68 Type fsmStateReasonType 69 peerDownReason peerDownReason 70 BGPNotification *bgp.BGPMessage 71 Data []byte 72 } 73 74 func newfsmStateReason(typ fsmStateReasonType, notif *bgp.BGPMessage, data []byte) *fsmStateReason { 75 var reasonCode peerDownReason 76 switch typ { 77 case fsmDying, fsmInvalidMsg, fsmNotificationSent, fsmHoldTimerExpired, fsmIdleTimerExpired, fsmRestartTimerExpired: 78 reasonCode = peerDownByLocal 79 case fsmAdminDown: 80 reasonCode = peerDownByLocalWithoutNotification 81 case fsmNotificationRecv, fsmGracefulRestart, fsmHardReset: 82 reasonCode = peerDownByRemote 83 case fsmReadFailed, fsmWriteFailed: 84 reasonCode = peerDownByRemoteWithoutNotification 85 } 86 return &fsmStateReason{ 87 Type: typ, 88 peerDownReason: reasonCode, 89 BGPNotification: notif, 90 Data: data, 91 } 92 } 93 94 func (r fsmStateReason) String() string { 95 switch r.Type { 96 case fsmDying: 97 return "dying" 98 case fsmAdminDown: 99 return "admin-down" 100 case fsmReadFailed: 101 return "read-failed" 102 case fsmWriteFailed: 103 return "write-failed" 104 case fsmNotificationSent: 105 body := r.BGPNotification.Body.(*bgp.BGPNotification) 106 return fmt.Sprintf("notification-sent %s", bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String()) 107 case fsmNotificationRecv: 108 body := r.BGPNotification.Body.(*bgp.BGPNotification) 109 return fmt.Sprintf("notification-received %s", bgp.NewNotificationErrorCode(body.ErrorCode, body.ErrorSubcode).String()) 110 case fsmHoldTimerExpired: 111 return "hold-timer-expired" 112 case fsmIdleTimerExpired: 113 return "idle-hold-timer-expired" 114 case fsmRestartTimerExpired: 115 return "restart-timer-expired" 116 case fsmGracefulRestart: 117 return "graceful-restart" 118 case fsmInvalidMsg: 119 return "invalid-msg" 120 case fsmNewConnection: 121 return "new-connection" 122 case fsmOpenMsgReceived: 123 return "open-msg-received" 124 case fsmOpenMsgNegotiated: 125 return "open-msg-negotiated" 126 case fsmHardReset: 127 return "hard-reset" 128 default: 129 return "unknown" 130 } 131 } 132 133 type fsmMsgType int 134 135 const ( 136 _ fsmMsgType = iota 137 fsmMsgStateChange 138 fsmMsgBGPMessage 139 fsmMsgRouteRefresh 140 ) 141 142 type fsmMsg struct { 143 MsgType fsmMsgType 144 MsgSrc string 145 MsgData interface{} 146 StateReason *fsmStateReason 147 PathList []*table.Path 148 timestamp time.Time 149 payload []byte 150 Version uint 151 } 152 153 type fsmOutgoingMsg struct { 154 Paths []*table.Path 155 Notification *bgp.BGPMessage 156 StayIdle bool 157 } 158 159 const ( 160 holdtimeOpensent = 240 161 holdtimeIdle = 5 162 ) 163 164 type adminState int 165 166 const ( 167 adminStateUp adminState = iota 168 adminStateDown 169 adminStatePfxCt 170 ) 171 172 func (s adminState) String() string { 173 switch s { 174 case adminStateUp: 175 return "adminStateUp" 176 case adminStateDown: 177 return "adminStateDown" 178 case adminStatePfxCt: 179 return "adminStatePfxCt" 180 default: 181 return "Unknown" 182 } 183 } 184 185 type adminStateOperation struct { 186 State adminState 187 Communication []byte 188 } 189 190 var fsmVersion uint 191 192 type fsm struct { 193 gConf *config.Global 194 pConf *config.Neighbor 195 lock sync.RWMutex 196 state bgp.FSMState 197 reason *fsmStateReason 198 conn net.Conn 199 connCh chan net.Conn 200 idleHoldTime float64 201 opensentHoldTime float64 202 adminState adminState 203 adminStateCh chan adminStateOperation 204 h *fsmHandler 205 rfMap map[bgp.RouteFamily]bgp.BGPAddPathMode 206 capMap map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface 207 recvOpen *bgp.BGPMessage 208 peerInfo *table.PeerInfo 209 policy *table.RoutingPolicy 210 gracefulRestartTimer *time.Timer 211 twoByteAsTrans bool 212 version uint 213 marshallingOptions *bgp.MarshallingOption 214 } 215 216 func (fsm *fsm) bgpMessageStateUpdate(MessageType uint8, isIn bool) { 217 fsm.lock.Lock() 218 defer fsm.lock.Unlock() 219 state := &fsm.pConf.State.Messages 220 timer := &fsm.pConf.Timers 221 if isIn { 222 state.Received.Total++ 223 } else { 224 state.Sent.Total++ 225 } 226 switch MessageType { 227 case bgp.BGP_MSG_OPEN: 228 if isIn { 229 state.Received.Open++ 230 } else { 231 state.Sent.Open++ 232 } 233 case bgp.BGP_MSG_UPDATE: 234 if isIn { 235 state.Received.Update++ 236 timer.State.UpdateRecvTime = time.Now().Unix() 237 } else { 238 state.Sent.Update++ 239 } 240 case bgp.BGP_MSG_NOTIFICATION: 241 if isIn { 242 state.Received.Notification++ 243 } else { 244 state.Sent.Notification++ 245 } 246 case bgp.BGP_MSG_KEEPALIVE: 247 if isIn { 248 state.Received.Keepalive++ 249 } else { 250 state.Sent.Keepalive++ 251 } 252 case bgp.BGP_MSG_ROUTE_REFRESH: 253 if isIn { 254 state.Received.Refresh++ 255 } else { 256 state.Sent.Refresh++ 257 } 258 default: 259 if isIn { 260 state.Received.Discarded++ 261 } else { 262 state.Sent.Discarded++ 263 } 264 } 265 } 266 267 func (fsm *fsm) bmpStatsUpdate(statType uint16, increment int) { 268 fsm.lock.Lock() 269 defer fsm.lock.Unlock() 270 stats := &fsm.pConf.State.Messages.Received 271 switch statType { 272 // TODO 273 // Support other stat types. 274 case bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE: 275 stats.WithdrawUpdate += uint32(increment) 276 case bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX: 277 stats.WithdrawPrefix += uint32(increment) 278 } 279 } 280 281 func newFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingPolicy) *fsm { 282 adminState := adminStateUp 283 if pConf.Config.AdminDown { 284 adminState = adminStateDown 285 } 286 pConf.State.SessionState = config.IntToSessionStateMap[int(bgp.BGP_FSM_IDLE)] 287 pConf.Timers.State.Downtime = time.Now().Unix() 288 fsmVersion++ 289 fsm := &fsm{ 290 gConf: gConf, 291 pConf: pConf, 292 state: bgp.BGP_FSM_IDLE, 293 connCh: make(chan net.Conn, 1), 294 opensentHoldTime: float64(holdtimeOpensent), 295 adminState: adminState, 296 adminStateCh: make(chan adminStateOperation, 1), 297 rfMap: make(map[bgp.RouteFamily]bgp.BGPAddPathMode), 298 capMap: make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface), 299 peerInfo: table.NewPeerInfo(gConf, pConf), 300 policy: policy, 301 gracefulRestartTimer: time.NewTimer(time.Hour), 302 version: fsmVersion, 303 } 304 fsm.gracefulRestartTimer.Stop() 305 return fsm 306 } 307 308 func (fsm *fsm) StateChange(nextState bgp.FSMState) { 309 fsm.lock.Lock() 310 defer fsm.lock.Unlock() 311 312 log.WithFields(log.Fields{ 313 "Topic": "Peer", 314 "Key": fsm.pConf.State.NeighborAddress, 315 "old": fsm.state.String(), 316 "new": nextState.String(), 317 "reason": fsm.reason, 318 }).Debug("state changed") 319 fsm.state = nextState 320 switch nextState { 321 case bgp.BGP_FSM_ESTABLISHED: 322 fsm.pConf.Timers.State.Uptime = time.Now().Unix() 323 fsm.pConf.State.EstablishedCount++ 324 // reset the state set by the previous session 325 fsm.twoByteAsTrans = false 326 if _, y := fsm.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER]; !y { 327 fsm.twoByteAsTrans = true 328 break 329 } 330 y := func() bool { 331 for _, c := range capabilitiesFromConfig(fsm.pConf) { 332 switch c.(type) { 333 case *bgp.CapFourOctetASNumber: 334 return true 335 } 336 } 337 return false 338 }() 339 if !y { 340 fsm.twoByteAsTrans = true 341 } 342 default: 343 fsm.pConf.Timers.State.Downtime = time.Now().Unix() 344 } 345 } 346 347 func hostport(addr net.Addr) (string, uint16) { 348 if addr != nil { 349 host, port, err := net.SplitHostPort(addr.String()) 350 if err != nil { 351 return "", 0 352 } 353 p, _ := strconv.ParseUint(port, 10, 16) 354 return host, uint16(p) 355 } 356 return "", 0 357 } 358 359 func (fsm *fsm) RemoteHostPort() (string, uint16) { 360 return hostport(fsm.conn.RemoteAddr()) 361 362 } 363 364 func (fsm *fsm) LocalHostPort() (string, uint16) { 365 return hostport(fsm.conn.LocalAddr()) 366 } 367 368 func (fsm *fsm) sendNotificationFromErrorMsg(e *bgp.MessageError) (*bgp.BGPMessage, error) { 369 fsm.lock.RLock() 370 established := fsm.h != nil && fsm.h.conn != nil 371 fsm.lock.RUnlock() 372 373 if established { 374 m := bgp.NewBGPNotificationMessage(e.TypeCode, e.SubTypeCode, e.Data) 375 b, _ := m.Serialize() 376 _, err := fsm.h.conn.Write(b) 377 if err == nil { 378 fsm.bgpMessageStateUpdate(m.Header.Type, false) 379 fsm.h.sentNotification = m 380 } 381 fsm.h.conn.Close() 382 log.WithFields(log.Fields{ 383 "Topic": "Peer", 384 "Key": fsm.pConf.State.NeighborAddress, 385 "Data": e, 386 }).Warn("sent notification") 387 return m, nil 388 } 389 return nil, fmt.Errorf("can't send notification to %s since TCP connection is not established", fsm.pConf.State.NeighborAddress) 390 } 391 392 func (fsm *fsm) sendNotification(code, subType uint8, data []byte, msg string) (*bgp.BGPMessage, error) { 393 e := bgp.NewMessageError(code, subType, data, msg) 394 return fsm.sendNotificationFromErrorMsg(e.(*bgp.MessageError)) 395 } 396 397 type fsmHandler struct { 398 fsm *fsm 399 conn net.Conn 400 msgCh *channels.InfiniteChannel 401 stateReasonCh chan fsmStateReason 402 incoming *channels.InfiniteChannel 403 stateCh chan *fsmMsg 404 outgoing *channels.InfiniteChannel 405 holdTimerResetCh chan bool 406 sentNotification *bgp.BGPMessage 407 ctx context.Context 408 ctxCancel context.CancelFunc 409 wg *sync.WaitGroup 410 } 411 412 func newFSMHandler(fsm *fsm, incoming *channels.InfiniteChannel, stateCh chan *fsmMsg, outgoing *channels.InfiniteChannel) *fsmHandler { 413 ctx, cancel := context.WithCancel(context.Background()) 414 h := &fsmHandler{ 415 fsm: fsm, 416 stateReasonCh: make(chan fsmStateReason, 2), 417 incoming: incoming, 418 stateCh: stateCh, 419 outgoing: outgoing, 420 holdTimerResetCh: make(chan bool, 2), 421 wg: &sync.WaitGroup{}, 422 ctx: ctx, 423 ctxCancel: cancel, 424 } 425 h.wg.Add(1) 426 go h.loop(ctx, h.wg) 427 return h 428 } 429 430 func (h *fsmHandler) idle(ctx context.Context) (bgp.FSMState, *fsmStateReason) { 431 fsm := h.fsm 432 433 fsm.lock.RLock() 434 idleHoldTimer := time.NewTimer(time.Second * time.Duration(fsm.idleHoldTime)) 435 fsm.lock.RUnlock() 436 437 for { 438 select { 439 case <-ctx.Done(): 440 return -1, newfsmStateReason(fsmDying, nil, nil) 441 case <-fsm.gracefulRestartTimer.C: 442 fsm.lock.RLock() 443 restarting := fsm.pConf.GracefulRestart.State.PeerRestarting 444 fsm.lock.RUnlock() 445 446 if restarting { 447 fsm.lock.RLock() 448 log.WithFields(log.Fields{ 449 "Topic": "Peer", 450 "Key": fsm.pConf.State.NeighborAddress, 451 "State": fsm.state.String(), 452 }).Warn("graceful restart timer expired") 453 fsm.lock.RUnlock() 454 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil) 455 } 456 case conn, ok := <-fsm.connCh: 457 if !ok { 458 break 459 } 460 conn.Close() 461 fsm.lock.RLock() 462 log.WithFields(log.Fields{ 463 "Topic": "Peer", 464 "Key": fsm.pConf.State.NeighborAddress, 465 "State": fsm.state.String(), 466 }).Warn("Closed an accepted connection") 467 fsm.lock.RUnlock() 468 469 case <-idleHoldTimer.C: 470 fsm.lock.RLock() 471 adminStateUp := fsm.adminState == adminStateUp 472 fsm.lock.RUnlock() 473 474 if adminStateUp { 475 fsm.lock.Lock() 476 log.WithFields(log.Fields{ 477 "Topic": "Peer", 478 "Key": fsm.pConf.State.NeighborAddress, 479 "Duration": fsm.idleHoldTime, 480 }).Debug("IdleHoldTimer expired") 481 fsm.idleHoldTime = holdtimeIdle 482 fsm.lock.Unlock() 483 return bgp.BGP_FSM_ACTIVE, newfsmStateReason(fsmIdleTimerExpired, nil, nil) 484 485 } else { 486 log.WithFields(log.Fields{"Topic": "Peer"}).Debug("IdleHoldTimer expired, but stay at idle because the admin state is DOWN") 487 } 488 489 case stateOp := <-fsm.adminStateCh: 490 err := h.changeadminState(stateOp.State) 491 if err == nil { 492 switch stateOp.State { 493 case adminStateDown: 494 // stop idle hold timer 495 idleHoldTimer.Stop() 496 497 case adminStateUp: 498 // restart idle hold timer 499 fsm.lock.RLock() 500 idleHoldTimer.Reset(time.Second * time.Duration(fsm.idleHoldTime)) 501 fsm.lock.RUnlock() 502 } 503 } 504 } 505 } 506 } 507 508 func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) { 509 defer wg.Done() 510 fsm := h.fsm 511 512 tick, addr, port, password, ttl, ttlMin, localAddress := func() (int, string, int, string, uint8, uint8, string) { 513 fsm.lock.RLock() 514 defer fsm.lock.RUnlock() 515 516 tick := int(fsm.pConf.Timers.Config.ConnectRetry) 517 if tick < minConnectRetry { 518 tick = minConnectRetry 519 } 520 521 addr := fsm.pConf.State.NeighborAddress 522 port := int(bgp.BGP_PORT) 523 if fsm.pConf.Transport.Config.RemotePort != 0 { 524 port = int(fsm.pConf.Transport.Config.RemotePort) 525 } 526 password := fsm.pConf.Config.AuthPassword 527 ttl := uint8(0) 528 ttlMin := uint8(0) 529 530 if fsm.pConf.TtlSecurity.Config.Enabled { 531 ttl = 255 532 ttlMin = fsm.pConf.TtlSecurity.Config.TtlMin 533 } else if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL { 534 ttl = 1 535 if fsm.pConf.EbgpMultihop.Config.Enabled { 536 ttl = fsm.pConf.EbgpMultihop.Config.MultihopTtl 537 } 538 } 539 return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.LocalAddress 540 }() 541 542 for { 543 r := rand.New(rand.NewSource(time.Now().UnixNano())) 544 timer := time.NewTimer(time.Duration(r.Intn(tick)+tick) * time.Second) 545 select { 546 case <-ctx.Done(): 547 log.WithFields(log.Fields{ 548 "Topic": "Peer", 549 "Key": addr, 550 }).Debug("stop connect loop") 551 timer.Stop() 552 return 553 case <-timer.C: 554 log.WithFields(log.Fields{ 555 "Topic": "Peer", 556 "Key": addr, 557 }).Debug("try to connect") 558 } 559 560 laddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(localAddress, "0")) 561 if err != nil { 562 log.WithFields(log.Fields{ 563 "Topic": "Peer", 564 "Key": addr, 565 }).Warnf("failed to resolve local address: %s", err) 566 } 567 568 if err == nil { 569 d := net.Dialer{ 570 LocalAddr: laddr, 571 Timeout: time.Duration(tick-1) * time.Second, 572 Control: func(network, address string, c syscall.RawConn) error { 573 return dialerControl(network, address, c, ttl, ttlMin, password) 574 }, 575 } 576 577 conn, err := d.DialContext(ctx, "tcp", net.JoinHostPort(addr, fmt.Sprintf("%d", port))) 578 select { 579 case <-ctx.Done(): 580 log.WithFields(log.Fields{ 581 "Topic": "Peer", 582 "Key": addr, 583 }).Debug("stop connect loop") 584 return 585 default: 586 } 587 588 if err == nil { 589 select { 590 case fsm.connCh <- conn: 591 return 592 default: 593 conn.Close() 594 log.WithFields(log.Fields{ 595 "Topic": "Peer", 596 "Key": addr, 597 }).Warn("active conn is closed to avoid being blocked") 598 } 599 } else { 600 log.WithFields(log.Fields{ 601 "Topic": "Peer", 602 "Key": addr, 603 }).Debugf("failed to connect: %s", err) 604 } 605 } 606 } 607 } 608 609 func (h *fsmHandler) active(ctx context.Context) (bgp.FSMState, *fsmStateReason) { 610 c, cancel := context.WithCancel(ctx) 611 612 var wg sync.WaitGroup 613 wg.Add(1) 614 go h.connectLoop(c, &wg) 615 616 defer func() { 617 cancel() 618 wg.Wait() 619 }() 620 621 fsm := h.fsm 622 for { 623 select { 624 case <-ctx.Done(): 625 return -1, newfsmStateReason(fsmDying, nil, nil) 626 case conn, ok := <-fsm.connCh: 627 if !ok { 628 break 629 } 630 fsm.lock.Lock() 631 fsm.conn = conn 632 fsm.lock.Unlock() 633 ttl := 0 634 ttlMin := 0 635 636 fsm.lock.RLock() 637 if fsm.pConf.TtlSecurity.Config.Enabled { 638 ttl = 255 639 ttlMin = int(fsm.pConf.TtlSecurity.Config.TtlMin) 640 } else if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL { 641 if fsm.pConf.EbgpMultihop.Config.Enabled { 642 ttl = int(fsm.pConf.EbgpMultihop.Config.MultihopTtl) 643 } else if fsm.pConf.Transport.Config.Ttl != 0 { 644 ttl = int(fsm.pConf.Transport.Config.Ttl) 645 } else { 646 ttl = 1 647 } 648 } else if fsm.pConf.Transport.Config.Ttl != 0 { 649 ttl = int(fsm.pConf.Transport.Config.Ttl) 650 } 651 if ttl != 0 { 652 if err := setTCPTTLSockopt(conn.(*net.TCPConn), ttl); err != nil { 653 log.WithFields(log.Fields{ 654 "Topic": "Peer", 655 "Key": fsm.pConf.Config.NeighborAddress, 656 "State": fsm.state.String(), 657 }).Warnf("cannot set TTL(=%d) for peer: %s", ttl, err) 658 } 659 } 660 if ttlMin != 0 { 661 if err := setTCPMinTTLSockopt(conn.(*net.TCPConn), ttlMin); err != nil { 662 log.WithFields(log.Fields{ 663 "Topic": "Peer", 664 "Key": fsm.pConf.Config.NeighborAddress, 665 "State": fsm.state.String(), 666 }).Warnf("cannot set minimal TTL(=%d) for peer: %s", ttl, err) 667 } 668 } 669 fsm.lock.RUnlock() 670 // we don't implement delayed open timer so move to opensent right 671 // away. 672 return bgp.BGP_FSM_OPENSENT, newfsmStateReason(fsmNewConnection, nil, nil) 673 case <-fsm.gracefulRestartTimer.C: 674 fsm.lock.RLock() 675 restarting := fsm.pConf.GracefulRestart.State.PeerRestarting 676 fsm.lock.RUnlock() 677 if restarting { 678 fsm.lock.RLock() 679 log.WithFields(log.Fields{ 680 "Topic": "Peer", 681 "Key": fsm.pConf.State.NeighborAddress, 682 "State": fsm.state.String(), 683 }).Warn("graceful restart timer expired") 684 fsm.lock.RUnlock() 685 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil) 686 } 687 case err := <-h.stateReasonCh: 688 return bgp.BGP_FSM_IDLE, &err 689 case stateOp := <-fsm.adminStateCh: 690 err := h.changeadminState(stateOp.State) 691 if err == nil { 692 switch stateOp.State { 693 case adminStateDown: 694 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmAdminDown, nil, nil) 695 case adminStateUp: 696 log.WithFields(log.Fields{ 697 "Topic": "Peer", 698 "Key": fsm.pConf.State.NeighborAddress, 699 "State": fsm.state.String(), 700 "adminState": stateOp.State.String(), 701 }).Panic("code logic bug") 702 } 703 } 704 } 705 } 706 } 707 708 func capAddPathFromConfig(pConf *config.Neighbor) bgp.ParameterCapabilityInterface { 709 tuples := make([]*bgp.CapAddPathTuple, 0, len(pConf.AfiSafis)) 710 for _, af := range pConf.AfiSafis { 711 var mode bgp.BGPAddPathMode 712 if af.AddPaths.State.Receive { 713 mode |= bgp.BGP_ADD_PATH_RECEIVE 714 } 715 if af.AddPaths.State.SendMax > 0 { 716 mode |= bgp.BGP_ADD_PATH_SEND 717 } 718 if mode > 0 { 719 tuples = append(tuples, bgp.NewCapAddPathTuple(af.State.Family, mode)) 720 } 721 } 722 if len(tuples) == 0 { 723 return nil 724 } 725 return bgp.NewCapAddPath(tuples) 726 } 727 728 func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInterface { 729 caps := make([]bgp.ParameterCapabilityInterface, 0, 4) 730 caps = append(caps, bgp.NewCapRouteRefresh()) 731 for _, af := range pConf.AfiSafis { 732 caps = append(caps, bgp.NewCapMultiProtocol(af.State.Family)) 733 } 734 caps = append(caps, bgp.NewCapFourOctetASNumber(pConf.Config.LocalAs)) 735 736 if c := pConf.GracefulRestart.Config; c.Enabled { 737 tuples := []*bgp.CapGracefulRestartTuple{} 738 ltuples := []*bgp.CapLongLivedGracefulRestartTuple{} 739 740 // RFC 4724 4.1 741 // To re-establish the session with its peer, the Restarting Speaker 742 // MUST set the "Restart State" bit in the Graceful Restart Capability 743 // of the OPEN message. 744 restarting := pConf.GracefulRestart.State.LocalRestarting 745 746 if !c.HelperOnly { 747 for i, rf := range pConf.AfiSafis { 748 if m := rf.MpGracefulRestart.Config; m.Enabled { 749 // When restarting, always flag forwaring bit. 750 // This can be a lie, depending on how gobgpd is used. 751 // For a route-server use-case, since a route-server 752 // itself doesn't forward packets, and the dataplane 753 // is a l2 switch which continues to work with no 754 // relation to bgpd, this behavior is ok. 755 // TODO consideration of other use-cases 756 tuples = append(tuples, bgp.NewCapGracefulRestartTuple(rf.State.Family, restarting)) 757 pConf.AfiSafis[i].MpGracefulRestart.State.Advertised = true 758 } 759 if m := rf.LongLivedGracefulRestart.Config; m.Enabled { 760 ltuples = append(ltuples, bgp.NewCapLongLivedGracefulRestartTuple(rf.State.Family, restarting, m.RestartTime)) 761 } 762 } 763 } 764 restartTime := c.RestartTime 765 notification := c.NotificationEnabled 766 caps = append(caps, bgp.NewCapGracefulRestart(restarting, notification, restartTime, tuples)) 767 if c.LongLivedEnabled { 768 caps = append(caps, bgp.NewCapLongLivedGracefulRestart(ltuples)) 769 } 770 } 771 772 // unnumbered BGP 773 if pConf.Config.NeighborInterface != "" { 774 tuples := []*bgp.CapExtendedNexthopTuple{} 775 families, _ := config.AfiSafis(pConf.AfiSafis).ToRfList() 776 for _, family := range families { 777 if family == bgp.RF_IPv6_UC { 778 continue 779 } 780 tuple := bgp.NewCapExtendedNexthopTuple(family, bgp.AFI_IP6) 781 tuples = append(tuples, tuple) 782 } 783 caps = append(caps, bgp.NewCapExtendedNexthop(tuples)) 784 } 785 786 // ADD-PATH Capability 787 if c := capAddPathFromConfig(pConf); c != nil { 788 caps = append(caps, capAddPathFromConfig(pConf)) 789 } 790 791 return caps 792 } 793 794 func buildopen(gConf *config.Global, pConf *config.Neighbor) *bgp.BGPMessage { 795 caps := capabilitiesFromConfig(pConf) 796 opt := bgp.NewOptionParameterCapability(caps) 797 holdTime := uint16(pConf.Timers.Config.HoldTime) 798 as := pConf.Config.LocalAs 799 if as > (1<<16)-1 { 800 as = bgp.AS_TRANS 801 } 802 return bgp.NewBGPOpenMessage(uint16(as), holdTime, gConf.Config.RouterId, 803 []bgp.OptionParameterInterface{opt}) 804 } 805 806 func readAll(conn net.Conn, length int) ([]byte, error) { 807 buf := make([]byte, length) 808 _, err := io.ReadFull(conn, buf) 809 if err != nil { 810 return nil, err 811 } 812 return buf, nil 813 } 814 815 func getPathAttrFromBGPUpdate(m *bgp.BGPUpdate, typ bgp.BGPAttrType) bgp.PathAttributeInterface { 816 for _, a := range m.PathAttributes { 817 if a.GetType() == typ { 818 return a 819 } 820 } 821 return nil 822 } 823 824 func hasOwnASLoop(ownAS uint32, limit int, asPath *bgp.PathAttributeAsPath) bool { 825 cnt := 0 826 for _, param := range asPath.Value { 827 for _, as := range param.GetAS() { 828 if as == ownAS { 829 cnt++ 830 if cnt > limit { 831 return true 832 } 833 } 834 } 835 } 836 return false 837 } 838 839 func extractRouteFamily(p *bgp.PathAttributeInterface) *bgp.RouteFamily { 840 attr := *p 841 842 var afi uint16 843 var safi uint8 844 845 switch a := attr.(type) { 846 case *bgp.PathAttributeMpReachNLRI: 847 afi = a.AFI 848 safi = a.SAFI 849 case *bgp.PathAttributeMpUnreachNLRI: 850 afi = a.AFI 851 safi = a.SAFI 852 default: 853 return nil 854 } 855 856 rf := bgp.AfiSafiToRouteFamily(afi, safi) 857 return &rf 858 } 859 860 func (h *fsmHandler) afiSafiDisable(rf bgp.RouteFamily) string { 861 h.fsm.lock.Lock() 862 defer h.fsm.lock.Unlock() 863 864 n := bgp.AddressFamilyNameMap[rf] 865 866 for i, a := range h.fsm.pConf.AfiSafis { 867 if string(a.Config.AfiSafiName) == n { 868 h.fsm.pConf.AfiSafis[i].State.Enabled = false 869 break 870 } 871 } 872 newList := make([]bgp.ParameterCapabilityInterface, 0) 873 for _, c := range h.fsm.capMap[bgp.BGP_CAP_MULTIPROTOCOL] { 874 if c.(*bgp.CapMultiProtocol).CapValue == rf { 875 continue 876 } 877 newList = append(newList, c) 878 } 879 h.fsm.capMap[bgp.BGP_CAP_MULTIPROTOCOL] = newList 880 return n 881 } 882 883 func (h *fsmHandler) handlingError(m *bgp.BGPMessage, e error, useRevisedError bool) bgp.ErrorHandling { 884 handling := bgp.ERROR_HANDLING_NONE 885 if m.Header.Type == bgp.BGP_MSG_UPDATE && useRevisedError { 886 factor := e.(*bgp.MessageError) 887 handling = factor.ErrorHandling 888 switch handling { 889 case bgp.ERROR_HANDLING_ATTRIBUTE_DISCARD: 890 h.fsm.lock.RLock() 891 log.WithFields(log.Fields{ 892 "Topic": "Peer", 893 "Key": h.fsm.pConf.State.NeighborAddress, 894 "State": h.fsm.state.String(), 895 "error": e, 896 }).Warn("Some attributes were discarded") 897 h.fsm.lock.RUnlock() 898 case bgp.ERROR_HANDLING_TREAT_AS_WITHDRAW: 899 m.Body = bgp.TreatAsWithdraw(m.Body.(*bgp.BGPUpdate)) 900 h.fsm.lock.RLock() 901 log.WithFields(log.Fields{ 902 "Topic": "Peer", 903 "Key": h.fsm.pConf.State.NeighborAddress, 904 "State": h.fsm.state.String(), 905 "error": e, 906 }).Warn("the received Update message was treated as withdraw") 907 h.fsm.lock.RUnlock() 908 case bgp.ERROR_HANDLING_AFISAFI_DISABLE: 909 rf := extractRouteFamily(factor.ErrorAttribute) 910 if rf == nil { 911 h.fsm.lock.RLock() 912 log.WithFields(log.Fields{ 913 "Topic": "Peer", 914 "Key": h.fsm.pConf.State.NeighborAddress, 915 "State": h.fsm.state.String(), 916 }).Warn("Error occurred during AFI/SAFI disabling") 917 h.fsm.lock.RUnlock() 918 } else { 919 n := h.afiSafiDisable(*rf) 920 h.fsm.lock.RLock() 921 log.WithFields(log.Fields{ 922 "Topic": "Peer", 923 "Key": h.fsm.pConf.State.NeighborAddress, 924 "State": h.fsm.state.String(), 925 "error": e, 926 }).Warnf("Capability %s was disabled", n) 927 h.fsm.lock.RUnlock() 928 } 929 } 930 } else { 931 handling = bgp.ERROR_HANDLING_SESSION_RESET 932 } 933 return handling 934 } 935 936 func (h *fsmHandler) recvMessageWithError() (*fsmMsg, error) { 937 sendToStateReasonCh := func(typ fsmStateReasonType, notif *bgp.BGPMessage) { 938 // probably doesn't happen but be cautious 939 select { 940 case h.stateReasonCh <- *newfsmStateReason(typ, notif, nil): 941 default: 942 } 943 } 944 945 headerBuf, err := readAll(h.conn, bgp.BGP_HEADER_LENGTH) 946 if err != nil { 947 sendToStateReasonCh(fsmReadFailed, nil) 948 return nil, err 949 } 950 951 hd := &bgp.BGPHeader{} 952 err = hd.DecodeFromBytes(headerBuf) 953 if err != nil { 954 h.fsm.bgpMessageStateUpdate(0, true) 955 h.fsm.lock.RLock() 956 log.WithFields(log.Fields{ 957 "Topic": "Peer", 958 "Key": h.fsm.pConf.State.NeighborAddress, 959 "State": h.fsm.state.String(), 960 "error": err, 961 }).Warn("Session will be reset due to malformed BGP Header") 962 fmsg := &fsmMsg{ 963 MsgType: fsmMsgBGPMessage, 964 MsgSrc: h.fsm.pConf.State.NeighborAddress, 965 MsgData: err, 966 Version: h.fsm.version, 967 } 968 h.fsm.lock.RUnlock() 969 return fmsg, err 970 } 971 972 bodyBuf, err := readAll(h.conn, int(hd.Len)-bgp.BGP_HEADER_LENGTH) 973 if err != nil { 974 sendToStateReasonCh(fsmReadFailed, nil) 975 return nil, err 976 } 977 978 now := time.Now() 979 handling := bgp.ERROR_HANDLING_NONE 980 981 h.fsm.lock.RLock() 982 useRevisedError := h.fsm.pConf.ErrorHandling.Config.TreatAsWithdraw 983 options := h.fsm.marshallingOptions 984 h.fsm.lock.RUnlock() 985 986 m, err := bgp.ParseBGPBody(hd, bodyBuf, options) 987 if err != nil { 988 handling = h.handlingError(m, err, useRevisedError) 989 h.fsm.bgpMessageStateUpdate(0, true) 990 } else { 991 h.fsm.bgpMessageStateUpdate(m.Header.Type, true) 992 err = bgp.ValidateBGPMessage(m) 993 } 994 h.fsm.lock.RLock() 995 fmsg := &fsmMsg{ 996 MsgType: fsmMsgBGPMessage, 997 MsgSrc: h.fsm.pConf.State.NeighborAddress, 998 timestamp: now, 999 Version: h.fsm.version, 1000 } 1001 h.fsm.lock.RUnlock() 1002 1003 switch handling { 1004 case bgp.ERROR_HANDLING_AFISAFI_DISABLE: 1005 fmsg.MsgData = m 1006 return fmsg, nil 1007 case bgp.ERROR_HANDLING_SESSION_RESET: 1008 h.fsm.lock.RLock() 1009 log.WithFields(log.Fields{ 1010 "Topic": "Peer", 1011 "Key": h.fsm.pConf.State.NeighborAddress, 1012 "State": h.fsm.state.String(), 1013 "error": err, 1014 }).Warn("Session will be reset due to malformed BGP message") 1015 h.fsm.lock.RUnlock() 1016 fmsg.MsgData = err 1017 return fmsg, err 1018 default: 1019 fmsg.MsgData = m 1020 1021 h.fsm.lock.RLock() 1022 establishedState := h.fsm.state == bgp.BGP_FSM_ESTABLISHED 1023 h.fsm.lock.RUnlock() 1024 1025 if establishedState { 1026 switch m.Header.Type { 1027 case bgp.BGP_MSG_ROUTE_REFRESH: 1028 fmsg.MsgType = fsmMsgRouteRefresh 1029 case bgp.BGP_MSG_UPDATE: 1030 body := m.Body.(*bgp.BGPUpdate) 1031 isEBGP := h.fsm.pConf.IsEBGPPeer(h.fsm.gConf) 1032 isConfed := h.fsm.pConf.IsConfederationMember(h.fsm.gConf) 1033 1034 fmsg.payload = make([]byte, len(headerBuf)+len(bodyBuf)) 1035 copy(fmsg.payload, headerBuf) 1036 copy(fmsg.payload[len(headerBuf):], bodyBuf) 1037 1038 h.fsm.lock.RLock() 1039 rfMap := h.fsm.rfMap 1040 h.fsm.lock.RUnlock() 1041 ok, err := bgp.ValidateUpdateMsg(body, rfMap, isEBGP, isConfed) 1042 if !ok { 1043 handling = h.handlingError(m, err, useRevisedError) 1044 } 1045 if handling == bgp.ERROR_HANDLING_SESSION_RESET { 1046 h.fsm.lock.RLock() 1047 log.WithFields(log.Fields{ 1048 "Topic": "Peer", 1049 "Key": h.fsm.pConf.State.NeighborAddress, 1050 "State": h.fsm.state.String(), 1051 "error": err, 1052 }).Warn("Session will be reset due to malformed BGP update message") 1053 h.fsm.lock.RUnlock() 1054 fmsg.MsgData = err 1055 return fmsg, err 1056 } 1057 1058 if routes := len(body.WithdrawnRoutes); routes > 0 { 1059 h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, 1) 1060 h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, routes) 1061 } else if attr := getPathAttrFromBGPUpdate(body, bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI); attr != nil { 1062 mpUnreach := attr.(*bgp.PathAttributeMpUnreachNLRI) 1063 if routes = len(mpUnreach.Value); routes > 0 { 1064 h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, 1) 1065 h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, routes) 1066 } 1067 } 1068 1069 table.UpdatePathAttrs4ByteAs(body) 1070 if err = table.UpdatePathAggregator4ByteAs(body); err != nil { 1071 fmsg.MsgData = err 1072 return fmsg, err 1073 } 1074 1075 h.fsm.lock.RLock() 1076 peerInfo := h.fsm.peerInfo 1077 h.fsm.lock.RUnlock() 1078 fmsg.PathList = table.ProcessMessage(m, peerInfo, fmsg.timestamp) 1079 fallthrough 1080 case bgp.BGP_MSG_KEEPALIVE: 1081 // if the length of h.holdTimerResetCh 1082 // isn't zero, the timer will be reset 1083 // soon anyway. 1084 select { 1085 case h.holdTimerResetCh <- true: 1086 default: 1087 } 1088 if m.Header.Type == bgp.BGP_MSG_KEEPALIVE { 1089 return nil, nil 1090 } 1091 case bgp.BGP_MSG_NOTIFICATION: 1092 body := m.Body.(*bgp.BGPNotification) 1093 if body.ErrorCode == bgp.BGP_ERROR_CEASE && (body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN || body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET) { 1094 communication, rest := decodeAdministrativeCommunication(body.Data) 1095 h.fsm.lock.RLock() 1096 log.WithFields(log.Fields{ 1097 "Topic": "Peer", 1098 "Key": h.fsm.pConf.State.NeighborAddress, 1099 "Code": body.ErrorCode, 1100 "Subcode": body.ErrorSubcode, 1101 "Communicated-Reason": communication, 1102 "Data": rest, 1103 }).Warn("received notification") 1104 h.fsm.lock.RUnlock() 1105 } else { 1106 h.fsm.lock.RLock() 1107 log.WithFields(log.Fields{ 1108 "Topic": "Peer", 1109 "Key": h.fsm.pConf.State.NeighborAddress, 1110 "Code": body.ErrorCode, 1111 "Subcode": body.ErrorSubcode, 1112 "Data": body.Data, 1113 }).Warn("received notification") 1114 h.fsm.lock.RUnlock() 1115 } 1116 1117 h.fsm.lock.RLock() 1118 s := h.fsm.pConf.GracefulRestart.State 1119 hardReset := s.Enabled && s.NotificationEnabled && body.ErrorCode == bgp.BGP_ERROR_CEASE && body.ErrorSubcode == bgp.BGP_ERROR_SUB_HARD_RESET 1120 h.fsm.lock.RUnlock() 1121 if hardReset { 1122 sendToStateReasonCh(fsmHardReset, m) 1123 } else { 1124 sendToStateReasonCh(fsmNotificationRecv, m) 1125 } 1126 return nil, nil 1127 } 1128 } 1129 } 1130 return fmsg, nil 1131 } 1132 1133 func (h *fsmHandler) recvMessage(ctx context.Context, wg *sync.WaitGroup) error { 1134 defer func() { 1135 h.msgCh.Close() 1136 wg.Done() 1137 }() 1138 fmsg, _ := h.recvMessageWithError() 1139 if fmsg != nil { 1140 h.msgCh.In() <- fmsg 1141 } 1142 return nil 1143 } 1144 1145 func open2Cap(open *bgp.BGPOpen, n *config.Neighbor) (map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface, map[bgp.RouteFamily]bgp.BGPAddPathMode) { 1146 capMap := make(map[bgp.BGPCapabilityCode][]bgp.ParameterCapabilityInterface) 1147 for _, p := range open.OptParams { 1148 if paramCap, y := p.(*bgp.OptionParameterCapability); y { 1149 for _, c := range paramCap.Capability { 1150 m, ok := capMap[c.Code()] 1151 if !ok { 1152 m = make([]bgp.ParameterCapabilityInterface, 0, 1) 1153 } 1154 capMap[c.Code()] = append(m, c) 1155 } 1156 } 1157 } 1158 1159 // squash add path cap 1160 if caps, y := capMap[bgp.BGP_CAP_ADD_PATH]; y { 1161 items := make([]*bgp.CapAddPathTuple, 0, len(caps)) 1162 for _, c := range caps { 1163 items = append(items, c.(*bgp.CapAddPath).Tuples...) 1164 } 1165 capMap[bgp.BGP_CAP_ADD_PATH] = []bgp.ParameterCapabilityInterface{bgp.NewCapAddPath(items)} 1166 } 1167 1168 // remote open message may not include multi-protocol capability 1169 if _, y := capMap[bgp.BGP_CAP_MULTIPROTOCOL]; !y { 1170 capMap[bgp.BGP_CAP_MULTIPROTOCOL] = []bgp.ParameterCapabilityInterface{bgp.NewCapMultiProtocol(bgp.RF_IPv4_UC)} 1171 } 1172 1173 local := n.CreateRfMap() 1174 remote := make(map[bgp.RouteFamily]bgp.BGPAddPathMode) 1175 for _, c := range capMap[bgp.BGP_CAP_MULTIPROTOCOL] { 1176 family := c.(*bgp.CapMultiProtocol).CapValue 1177 remote[family] = bgp.BGP_ADD_PATH_NONE 1178 for _, a := range capMap[bgp.BGP_CAP_ADD_PATH] { 1179 for _, i := range a.(*bgp.CapAddPath).Tuples { 1180 if i.RouteFamily == family { 1181 remote[family] = i.Mode 1182 } 1183 } 1184 } 1185 } 1186 negotiated := make(map[bgp.RouteFamily]bgp.BGPAddPathMode) 1187 for family, mode := range local { 1188 if m, y := remote[family]; y { 1189 n := bgp.BGP_ADD_PATH_NONE 1190 if mode&bgp.BGP_ADD_PATH_SEND > 0 && m&bgp.BGP_ADD_PATH_RECEIVE > 0 { 1191 n |= bgp.BGP_ADD_PATH_SEND 1192 } 1193 if mode&bgp.BGP_ADD_PATH_RECEIVE > 0 && m&bgp.BGP_ADD_PATH_SEND > 0 { 1194 n |= bgp.BGP_ADD_PATH_RECEIVE 1195 } 1196 negotiated[family] = n 1197 } 1198 } 1199 return capMap, negotiated 1200 } 1201 1202 func (h *fsmHandler) opensent(ctx context.Context) (bgp.FSMState, *fsmStateReason) { 1203 fsm := h.fsm 1204 1205 fsm.lock.RLock() 1206 m := buildopen(fsm.gConf, fsm.pConf) 1207 fsm.lock.RUnlock() 1208 1209 b, _ := m.Serialize() 1210 fsm.conn.Write(b) 1211 fsm.bgpMessageStateUpdate(m.Header.Type, false) 1212 1213 h.msgCh = channels.NewInfiniteChannel() 1214 1215 fsm.lock.RLock() 1216 h.conn = fsm.conn 1217 fsm.lock.RUnlock() 1218 1219 var wg sync.WaitGroup 1220 wg.Add(1) 1221 defer wg.Wait() 1222 go h.recvMessage(ctx, &wg) 1223 1224 // RFC 4271 P.60 1225 // sets its HoldTimer to a large value 1226 // A HoldTimer value of 4 minutes is suggested as a "large value" 1227 // for the HoldTimer 1228 fsm.lock.RLock() 1229 holdTimer := time.NewTimer(time.Second * time.Duration(fsm.opensentHoldTime)) 1230 fsm.lock.RUnlock() 1231 1232 for { 1233 select { 1234 case <-ctx.Done(): 1235 h.conn.Close() 1236 return -1, newfsmStateReason(fsmDying, nil, nil) 1237 case conn, ok := <-fsm.connCh: 1238 if !ok { 1239 break 1240 } 1241 conn.Close() 1242 fsm.lock.RLock() 1243 log.WithFields(log.Fields{ 1244 "Topic": "Peer", 1245 "Key": fsm.pConf.State.NeighborAddress, 1246 "State": fsm.state.String(), 1247 }).Warn("Closed an accepted connection") 1248 fsm.lock.RUnlock() 1249 case <-fsm.gracefulRestartTimer.C: 1250 fsm.lock.RLock() 1251 restarting := fsm.pConf.GracefulRestart.State.PeerRestarting 1252 fsm.lock.RUnlock() 1253 if restarting { 1254 fsm.lock.RLock() 1255 log.WithFields(log.Fields{ 1256 "Topic": "Peer", 1257 "Key": fsm.pConf.State.NeighborAddress, 1258 "State": fsm.state.String(), 1259 }).Warn("graceful restart timer expired") 1260 fsm.lock.RUnlock() 1261 h.conn.Close() 1262 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil) 1263 } 1264 case i, ok := <-h.msgCh.Out(): 1265 if !ok { 1266 continue 1267 } 1268 e := i.(*fsmMsg) 1269 switch e.MsgData.(type) { 1270 case *bgp.BGPMessage: 1271 m := e.MsgData.(*bgp.BGPMessage) 1272 if m.Header.Type == bgp.BGP_MSG_OPEN { 1273 fsm.lock.Lock() 1274 fsm.recvOpen = m 1275 fsm.lock.Unlock() 1276 1277 body := m.Body.(*bgp.BGPOpen) 1278 1279 fsm.lock.RLock() 1280 fsmPeerAS := fsm.pConf.Config.PeerAs 1281 fsm.lock.RUnlock() 1282 peerAs, err := bgp.ValidateOpenMsg(body, fsmPeerAS) 1283 if err != nil { 1284 m, _ := fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError)) 1285 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil) 1286 } 1287 1288 // ASN negotiation was skipped 1289 fsm.lock.RLock() 1290 asnNegotiationSkipped := fsm.pConf.Config.PeerAs == 0 1291 fsm.lock.RUnlock() 1292 if asnNegotiationSkipped { 1293 fsm.lock.Lock() 1294 typ := config.PEER_TYPE_EXTERNAL 1295 if fsm.peerInfo.LocalAS == peerAs { 1296 typ = config.PEER_TYPE_INTERNAL 1297 } 1298 fsm.pConf.State.PeerType = typ 1299 log.WithFields(log.Fields{ 1300 "Topic": "Peer", 1301 "Key": fsm.pConf.State.NeighborAddress, 1302 "State": fsm.state.String(), 1303 }).Infof("skipped asn negotiation: peer-as: %d, peer-type: %s", peerAs, typ) 1304 fsm.lock.Unlock() 1305 } else { 1306 fsm.lock.Lock() 1307 fsm.pConf.State.PeerType = fsm.pConf.Config.PeerType 1308 fsm.lock.Unlock() 1309 } 1310 fsm.lock.Lock() 1311 fsm.pConf.State.PeerAs = peerAs 1312 fsm.peerInfo.AS = peerAs 1313 fsm.peerInfo.ID = body.ID 1314 fsm.capMap, fsm.rfMap = open2Cap(body, fsm.pConf) 1315 1316 if _, y := fsm.capMap[bgp.BGP_CAP_ADD_PATH]; y { 1317 fsm.marshallingOptions = &bgp.MarshallingOption{ 1318 AddPath: fsm.rfMap, 1319 } 1320 } else { 1321 fsm.marshallingOptions = nil 1322 } 1323 1324 // calculate HoldTime 1325 // RFC 4271 P.13 1326 // a BGP speaker MUST calculate the value of the Hold Timer 1327 // by using the smaller of its configured Hold Time and the Hold Time 1328 // received in the OPEN message. 1329 holdTime := float64(body.HoldTime) 1330 myHoldTime := fsm.pConf.Timers.Config.HoldTime 1331 if holdTime > myHoldTime { 1332 fsm.pConf.Timers.State.NegotiatedHoldTime = myHoldTime 1333 } else { 1334 fsm.pConf.Timers.State.NegotiatedHoldTime = holdTime 1335 } 1336 1337 keepalive := fsm.pConf.Timers.Config.KeepaliveInterval 1338 if n := fsm.pConf.Timers.State.NegotiatedHoldTime; n < myHoldTime { 1339 keepalive = n / 3 1340 } 1341 fsm.pConf.Timers.State.KeepaliveInterval = keepalive 1342 1343 gr, ok := fsm.capMap[bgp.BGP_CAP_GRACEFUL_RESTART] 1344 if fsm.pConf.GracefulRestart.Config.Enabled && ok { 1345 state := &fsm.pConf.GracefulRestart.State 1346 state.Enabled = true 1347 cap := gr[len(gr)-1].(*bgp.CapGracefulRestart) 1348 state.PeerRestartTime = uint16(cap.Time) 1349 1350 for _, t := range cap.Tuples { 1351 n := bgp.AddressFamilyNameMap[bgp.AfiSafiToRouteFamily(t.AFI, t.SAFI)] 1352 for i, a := range fsm.pConf.AfiSafis { 1353 if string(a.Config.AfiSafiName) == n { 1354 fsm.pConf.AfiSafis[i].MpGracefulRestart.State.Enabled = true 1355 fsm.pConf.AfiSafis[i].MpGracefulRestart.State.Received = true 1356 break 1357 } 1358 } 1359 } 1360 1361 // RFC 4724 4.1 1362 // To re-establish the session with its peer, the Restarting Speaker 1363 // MUST set the "Restart State" bit in the Graceful Restart Capability 1364 // of the OPEN message. 1365 if fsm.pConf.GracefulRestart.State.PeerRestarting && cap.Flags&0x08 == 0 { 1366 log.WithFields(log.Fields{ 1367 "Topic": "Peer", 1368 "Key": fsm.pConf.State.NeighborAddress, 1369 "State": fsm.state.String(), 1370 }).Warn("restart flag is not set") 1371 // send notification? 1372 h.conn.Close() 1373 fsm.lock.Unlock() 1374 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, nil, nil) 1375 } 1376 1377 // RFC 4724 3 1378 // The most significant bit is defined as the Restart State (R) 1379 // bit, ...(snip)... When set (value 1), this bit 1380 // indicates that the BGP speaker has restarted, and its peer MUST 1381 // NOT wait for the End-of-RIB marker from the speaker before 1382 // advertising routing information to the speaker. 1383 if fsm.pConf.GracefulRestart.State.LocalRestarting && cap.Flags&0x08 != 0 { 1384 log.WithFields(log.Fields{ 1385 "Topic": "Peer", 1386 "Key": fsm.pConf.State.NeighborAddress, 1387 "State": fsm.state.String(), 1388 }).Debug("peer has restarted, skipping wait for EOR") 1389 for i := range fsm.pConf.AfiSafis { 1390 fsm.pConf.AfiSafis[i].MpGracefulRestart.State.EndOfRibReceived = true 1391 } 1392 } 1393 if fsm.pConf.GracefulRestart.Config.NotificationEnabled && cap.Flags&0x04 > 0 { 1394 fsm.pConf.GracefulRestart.State.NotificationEnabled = true 1395 } 1396 } 1397 llgr, ok2 := fsm.capMap[bgp.BGP_CAP_LONG_LIVED_GRACEFUL_RESTART] 1398 if fsm.pConf.GracefulRestart.Config.LongLivedEnabled && ok && ok2 { 1399 fsm.pConf.GracefulRestart.State.LongLivedEnabled = true 1400 cap := llgr[len(llgr)-1].(*bgp.CapLongLivedGracefulRestart) 1401 for _, t := range cap.Tuples { 1402 n := bgp.AddressFamilyNameMap[bgp.AfiSafiToRouteFamily(t.AFI, t.SAFI)] 1403 for i, a := range fsm.pConf.AfiSafis { 1404 if string(a.Config.AfiSafiName) == n { 1405 fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.Enabled = true 1406 fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.Received = true 1407 fsm.pConf.AfiSafis[i].LongLivedGracefulRestart.State.PeerRestartTime = t.RestartTime 1408 break 1409 } 1410 } 1411 } 1412 } 1413 1414 fsm.lock.Unlock() 1415 msg := bgp.NewBGPKeepAliveMessage() 1416 b, _ := msg.Serialize() 1417 fsm.conn.Write(b) 1418 fsm.bgpMessageStateUpdate(msg.Header.Type, false) 1419 return bgp.BGP_FSM_OPENCONFIRM, newfsmStateReason(fsmOpenMsgReceived, nil, nil) 1420 } else { 1421 // send notification? 1422 h.conn.Close() 1423 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, nil, nil) 1424 } 1425 case *bgp.MessageError: 1426 m, _ := fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError)) 1427 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil) 1428 default: 1429 log.WithFields(log.Fields{ 1430 "Topic": "Peer", 1431 "Key": fsm.pConf.State.NeighborAddress, 1432 "State": fsm.state.String(), 1433 "Data": e.MsgData, 1434 }).Panic("unknown msg type") 1435 } 1436 case err := <-h.stateReasonCh: 1437 h.conn.Close() 1438 return bgp.BGP_FSM_IDLE, &err 1439 case <-holdTimer.C: 1440 m, _ := fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired") 1441 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmHoldTimerExpired, m, nil) 1442 case stateOp := <-fsm.adminStateCh: 1443 err := h.changeadminState(stateOp.State) 1444 if err == nil { 1445 switch stateOp.State { 1446 case adminStateDown: 1447 h.conn.Close() 1448 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmAdminDown, m, nil) 1449 case adminStateUp: 1450 log.WithFields(log.Fields{ 1451 "Topic": "Peer", 1452 "Key": fsm.pConf.State.NeighborAddress, 1453 "State": fsm.state.String(), 1454 "adminState": stateOp.State.String(), 1455 }).Panic("code logic bug") 1456 } 1457 } 1458 } 1459 } 1460 } 1461 1462 func keepaliveTicker(fsm *fsm) *time.Ticker { 1463 fsm.lock.RLock() 1464 defer fsm.lock.RUnlock() 1465 1466 negotiatedTime := fsm.pConf.Timers.State.NegotiatedHoldTime 1467 if negotiatedTime == 0 { 1468 return &time.Ticker{} 1469 } 1470 sec := time.Second * time.Duration(fsm.pConf.Timers.State.KeepaliveInterval) 1471 if sec == 0 { 1472 sec = time.Second 1473 } 1474 return time.NewTicker(sec) 1475 } 1476 1477 func (h *fsmHandler) openconfirm(ctx context.Context) (bgp.FSMState, *fsmStateReason) { 1478 fsm := h.fsm 1479 ticker := keepaliveTicker(fsm) 1480 h.msgCh = channels.NewInfiniteChannel() 1481 fsm.lock.RLock() 1482 h.conn = fsm.conn 1483 1484 var wg sync.WaitGroup 1485 defer wg.Wait() 1486 wg.Add(1) 1487 go h.recvMessage(ctx, &wg) 1488 1489 var holdTimer *time.Timer 1490 if fsm.pConf.Timers.State.NegotiatedHoldTime == 0 { 1491 holdTimer = &time.Timer{} 1492 } else { 1493 // RFC 4271 P.65 1494 // sets the HoldTimer according to the negotiated value 1495 holdTimer = time.NewTimer(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime)) 1496 } 1497 fsm.lock.RUnlock() 1498 1499 for { 1500 select { 1501 case <-ctx.Done(): 1502 h.conn.Close() 1503 return -1, newfsmStateReason(fsmDying, nil, nil) 1504 case conn, ok := <-fsm.connCh: 1505 if !ok { 1506 break 1507 } 1508 conn.Close() 1509 fsm.lock.RLock() 1510 log.WithFields(log.Fields{ 1511 "Topic": "Peer", 1512 "Key": fsm.pConf.State.NeighborAddress, 1513 "State": fsm.state.String(), 1514 }).Warn("Closed an accepted connection") 1515 fsm.lock.RUnlock() 1516 case <-fsm.gracefulRestartTimer.C: 1517 fsm.lock.RLock() 1518 restarting := fsm.pConf.GracefulRestart.State.PeerRestarting 1519 fsm.lock.RUnlock() 1520 if restarting { 1521 fsm.lock.RLock() 1522 log.WithFields(log.Fields{ 1523 "Topic": "Peer", 1524 "Key": fsm.pConf.State.NeighborAddress, 1525 "State": fsm.state.String(), 1526 }).Warn("graceful restart timer expired") 1527 fsm.lock.RUnlock() 1528 h.conn.Close() 1529 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmRestartTimerExpired, nil, nil) 1530 } 1531 case <-ticker.C: 1532 m := bgp.NewBGPKeepAliveMessage() 1533 b, _ := m.Serialize() 1534 // TODO: check error 1535 fsm.conn.Write(b) 1536 fsm.bgpMessageStateUpdate(m.Header.Type, false) 1537 case i, ok := <-h.msgCh.Out(): 1538 if !ok { 1539 continue 1540 } 1541 e := i.(*fsmMsg) 1542 switch e.MsgData.(type) { 1543 case *bgp.BGPMessage: 1544 m := e.MsgData.(*bgp.BGPMessage) 1545 if m.Header.Type == bgp.BGP_MSG_KEEPALIVE { 1546 return bgp.BGP_FSM_ESTABLISHED, newfsmStateReason(fsmOpenMsgNegotiated, nil, nil) 1547 } 1548 // send notification ? 1549 h.conn.Close() 1550 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, nil, nil) 1551 case *bgp.MessageError: 1552 m, _ := fsm.sendNotificationFromErrorMsg(e.MsgData.(*bgp.MessageError)) 1553 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil) 1554 default: 1555 log.WithFields(log.Fields{ 1556 "Topic": "Peer", 1557 "Key": fsm.pConf.State.NeighborAddress, 1558 "State": fsm.state.String(), 1559 "Data": e.MsgData, 1560 }).Panic("unknown msg type") 1561 } 1562 case err := <-h.stateReasonCh: 1563 h.conn.Close() 1564 return bgp.BGP_FSM_IDLE, &err 1565 case <-holdTimer.C: 1566 m, _ := fsm.sendNotification(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil, "hold timer expired") 1567 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmHoldTimerExpired, m, nil) 1568 case stateOp := <-fsm.adminStateCh: 1569 err := h.changeadminState(stateOp.State) 1570 if err == nil { 1571 switch stateOp.State { 1572 case adminStateDown: 1573 h.conn.Close() 1574 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmAdminDown, nil, nil) 1575 case adminStateUp: 1576 log.WithFields(log.Fields{ 1577 "Topic": "Peer", 1578 "Key": fsm.pConf.State.NeighborAddress, 1579 "State": fsm.state.String(), 1580 "adminState": stateOp.State.String(), 1581 }).Panic("code logic bug") 1582 } 1583 } 1584 } 1585 } 1586 } 1587 1588 func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) error { 1589 defer wg.Done() 1590 conn := h.conn 1591 fsm := h.fsm 1592 ticker := keepaliveTicker(fsm) 1593 send := func(m *bgp.BGPMessage) error { 1594 fsm.lock.RLock() 1595 if fsm.twoByteAsTrans && m.Header.Type == bgp.BGP_MSG_UPDATE { 1596 log.WithFields(log.Fields{ 1597 "Topic": "Peer", 1598 "Key": fsm.pConf.State.NeighborAddress, 1599 "State": fsm.state.String(), 1600 "Data": m, 1601 }).Debug("update for 2byte AS peer") 1602 table.UpdatePathAttrs2ByteAs(m.Body.(*bgp.BGPUpdate)) 1603 table.UpdatePathAggregator2ByteAs(m.Body.(*bgp.BGPUpdate)) 1604 } 1605 b, err := m.Serialize(h.fsm.marshallingOptions) 1606 fsm.lock.RUnlock() 1607 if err != nil { 1608 fsm.lock.RLock() 1609 log.WithFields(log.Fields{ 1610 "Topic": "Peer", 1611 "Key": fsm.pConf.State.NeighborAddress, 1612 "State": fsm.state.String(), 1613 "Data": err, 1614 }).Warn("failed to serialize") 1615 fsm.lock.RUnlock() 1616 fsm.bgpMessageStateUpdate(0, false) 1617 return nil 1618 } 1619 fsm.lock.RLock() 1620 err = conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime))) 1621 fsm.lock.RUnlock() 1622 if err != nil { 1623 h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil) 1624 conn.Close() 1625 return fmt.Errorf("failed to set write deadline") 1626 } 1627 _, err = conn.Write(b) 1628 if err != nil { 1629 fsm.lock.RLock() 1630 log.WithFields(log.Fields{ 1631 "Topic": "Peer", 1632 "Key": fsm.pConf.State.NeighborAddress, 1633 "State": fsm.state.String(), 1634 "Data": err, 1635 }).Warn("failed to send") 1636 fsm.lock.RUnlock() 1637 h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil) 1638 conn.Close() 1639 return fmt.Errorf("closed") 1640 } 1641 fsm.bgpMessageStateUpdate(m.Header.Type, false) 1642 1643 switch m.Header.Type { 1644 case bgp.BGP_MSG_NOTIFICATION: 1645 body := m.Body.(*bgp.BGPNotification) 1646 if body.ErrorCode == bgp.BGP_ERROR_CEASE && (body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN || body.ErrorSubcode == bgp.BGP_ERROR_SUB_ADMINISTRATIVE_RESET) { 1647 communication, rest := decodeAdministrativeCommunication(body.Data) 1648 fsm.lock.RLock() 1649 log.WithFields(log.Fields{ 1650 "Topic": "Peer", 1651 "Key": fsm.pConf.State.NeighborAddress, 1652 "State": fsm.state.String(), 1653 "Code": body.ErrorCode, 1654 "Subcode": body.ErrorSubcode, 1655 "Communicated-Reason": communication, 1656 "Data": rest, 1657 }).Warn("sent notification") 1658 fsm.lock.RUnlock() 1659 } else { 1660 fsm.lock.RLock() 1661 log.WithFields(log.Fields{ 1662 "Topic": "Peer", 1663 "Key": fsm.pConf.State.NeighborAddress, 1664 "State": fsm.state.String(), 1665 "Code": body.ErrorCode, 1666 "Subcode": body.ErrorSubcode, 1667 "Data": body.Data, 1668 }).Warn("sent notification") 1669 fsm.lock.RUnlock() 1670 } 1671 h.stateReasonCh <- *newfsmStateReason(fsmNotificationSent, m, nil) 1672 conn.Close() 1673 return fmt.Errorf("closed") 1674 case bgp.BGP_MSG_UPDATE: 1675 update := m.Body.(*bgp.BGPUpdate) 1676 fsm.lock.RLock() 1677 log.WithFields(log.Fields{ 1678 "Topic": "Peer", 1679 "Key": fsm.pConf.State.NeighborAddress, 1680 "State": fsm.state.String(), 1681 "nlri": update.NLRI, 1682 "withdrawals": update.WithdrawnRoutes, 1683 "attributes": update.PathAttributes, 1684 }).Debug("sent update") 1685 fsm.lock.RUnlock() 1686 default: 1687 fsm.lock.RLock() 1688 log.WithFields(log.Fields{ 1689 "Topic": "Peer", 1690 "Key": fsm.pConf.State.NeighborAddress, 1691 "State": fsm.state.String(), 1692 "data": m, 1693 }).Debug("sent") 1694 fsm.lock.RUnlock() 1695 } 1696 return nil 1697 } 1698 1699 for { 1700 select { 1701 case <-ctx.Done(): 1702 return nil 1703 case o := <-h.outgoing.Out(): 1704 switch m := o.(type) { 1705 case *fsmOutgoingMsg: 1706 h.fsm.lock.RLock() 1707 options := h.fsm.marshallingOptions 1708 h.fsm.lock.RUnlock() 1709 for _, msg := range table.CreateUpdateMsgFromPaths(m.Paths, options) { 1710 if err := send(msg); err != nil { 1711 return nil 1712 } 1713 } 1714 if m.Notification != nil { 1715 if m.StayIdle { 1716 // current user is only prefix-limit 1717 // fix me if this is not the case 1718 h.changeadminState(adminStatePfxCt) 1719 } 1720 if err := send(m.Notification); err != nil { 1721 return nil 1722 } 1723 } 1724 default: 1725 return nil 1726 } 1727 case <-ticker.C: 1728 if err := send(bgp.NewBGPKeepAliveMessage()); err != nil { 1729 return nil 1730 } 1731 } 1732 } 1733 } 1734 1735 func (h *fsmHandler) recvMessageloop(ctx context.Context, wg *sync.WaitGroup) error { 1736 defer wg.Done() 1737 for { 1738 fmsg, err := h.recvMessageWithError() 1739 if fmsg != nil { 1740 h.msgCh.In() <- fmsg 1741 } 1742 if err != nil { 1743 return nil 1744 } 1745 } 1746 } 1747 1748 func (h *fsmHandler) established(ctx context.Context) (bgp.FSMState, *fsmStateReason) { 1749 var wg sync.WaitGroup 1750 fsm := h.fsm 1751 fsm.lock.Lock() 1752 h.conn = fsm.conn 1753 fsm.lock.Unlock() 1754 1755 defer wg.Wait() 1756 wg.Add(2) 1757 1758 go h.sendMessageloop(ctx, &wg) 1759 h.msgCh = h.incoming 1760 go h.recvMessageloop(ctx, &wg) 1761 1762 var holdTimer *time.Timer 1763 if fsm.pConf.Timers.State.NegotiatedHoldTime == 0 { 1764 holdTimer = &time.Timer{} 1765 } else { 1766 fsm.lock.RLock() 1767 holdTimer = time.NewTimer(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime)) 1768 fsm.lock.RUnlock() 1769 } 1770 1771 fsm.gracefulRestartTimer.Stop() 1772 1773 for { 1774 select { 1775 case <-ctx.Done(): 1776 h.conn.Close() 1777 return -1, newfsmStateReason(fsmDying, nil, nil) 1778 case conn, ok := <-fsm.connCh: 1779 if !ok { 1780 break 1781 } 1782 conn.Close() 1783 fsm.lock.RLock() 1784 log.WithFields(log.Fields{ 1785 "Topic": "Peer", 1786 "Key": fsm.pConf.State.NeighborAddress, 1787 "State": fsm.state.String(), 1788 }).Warn("Closed an accepted connection") 1789 fsm.lock.RUnlock() 1790 case err := <-h.stateReasonCh: 1791 h.conn.Close() 1792 // if recv goroutine hit an error and sent to 1793 // stateReasonCh, then tx goroutine might take 1794 // long until it exits because it waits for 1795 // ctx.Done() or keepalive timer. So let kill 1796 // it now. 1797 h.outgoing.In() <- err 1798 fsm.lock.RLock() 1799 if s := fsm.pConf.GracefulRestart.State; s.Enabled && 1800 (s.NotificationEnabled && err.Type == fsmNotificationRecv || 1801 err.Type == fsmReadFailed || 1802 err.Type == fsmWriteFailed) { 1803 err = *newfsmStateReason(fsmGracefulRestart, nil, nil) 1804 log.WithFields(log.Fields{ 1805 "Topic": "Peer", 1806 "Key": fsm.pConf.State.NeighborAddress, 1807 "State": fsm.state.String(), 1808 }).Info("peer graceful restart") 1809 fsm.gracefulRestartTimer.Reset(time.Duration(fsm.pConf.GracefulRestart.State.PeerRestartTime) * time.Second) 1810 } 1811 fsm.lock.RUnlock() 1812 return bgp.BGP_FSM_IDLE, &err 1813 case <-holdTimer.C: 1814 fsm.lock.RLock() 1815 log.WithFields(log.Fields{ 1816 "Topic": "Peer", 1817 "Key": fsm.pConf.State.NeighborAddress, 1818 "State": fsm.state.String(), 1819 }).Warn("hold timer expired") 1820 fsm.lock.RUnlock() 1821 m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil) 1822 h.outgoing.In() <- &fsmOutgoingMsg{Notification: m} 1823 return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmHoldTimerExpired, m, nil) 1824 case <-h.holdTimerResetCh: 1825 fsm.lock.RLock() 1826 if fsm.pConf.Timers.State.NegotiatedHoldTime != 0 { 1827 holdTimer.Reset(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime)) 1828 } 1829 fsm.lock.RUnlock() 1830 case stateOp := <-fsm.adminStateCh: 1831 err := h.changeadminState(stateOp.State) 1832 if err == nil { 1833 switch stateOp.State { 1834 case adminStateDown: 1835 m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, stateOp.Communication) 1836 h.outgoing.In() <- &fsmOutgoingMsg{Notification: m} 1837 } 1838 } 1839 } 1840 } 1841 } 1842 1843 func (h *fsmHandler) loop(ctx context.Context, wg *sync.WaitGroup) error { 1844 defer wg.Done() 1845 1846 fsm := h.fsm 1847 fsm.lock.RLock() 1848 oldState := fsm.state 1849 fsm.lock.RUnlock() 1850 1851 var reason *fsmStateReason 1852 nextState := bgp.FSMState(-1) 1853 fsm.lock.RLock() 1854 fsmState := fsm.state 1855 fsm.lock.RUnlock() 1856 1857 switch fsmState { 1858 case bgp.BGP_FSM_IDLE: 1859 nextState, reason = h.idle(ctx) 1860 // case bgp.BGP_FSM_CONNECT: 1861 // nextState = h.connect() 1862 case bgp.BGP_FSM_ACTIVE: 1863 nextState, reason = h.active(ctx) 1864 case bgp.BGP_FSM_OPENSENT: 1865 nextState, reason = h.opensent(ctx) 1866 case bgp.BGP_FSM_OPENCONFIRM: 1867 nextState, reason = h.openconfirm(ctx) 1868 case bgp.BGP_FSM_ESTABLISHED: 1869 nextState, reason = h.established(ctx) 1870 } 1871 1872 fsm.lock.RLock() 1873 fsm.reason = reason 1874 1875 if nextState == bgp.BGP_FSM_ESTABLISHED && oldState == bgp.BGP_FSM_OPENCONFIRM { 1876 log.WithFields(log.Fields{ 1877 "Topic": "Peer", 1878 "Key": fsm.pConf.State.NeighborAddress, 1879 "State": fsm.state.String(), 1880 }).Info("Peer Up") 1881 } 1882 1883 if oldState == bgp.BGP_FSM_ESTABLISHED { 1884 // The main goroutine sent the notificaiton due to 1885 // deconfiguration or something. 1886 reason := fsm.reason 1887 if fsm.h.sentNotification != nil { 1888 reason.Type = fsmNotificationSent 1889 reason.peerDownReason = peerDownByLocal 1890 reason.BGPNotification = fsm.h.sentNotification 1891 } 1892 log.WithFields(log.Fields{ 1893 "Topic": "Peer", 1894 "Key": fsm.pConf.State.NeighborAddress, 1895 "State": fsm.state.String(), 1896 "Reason": reason.String(), 1897 }).Info("Peer Down") 1898 } 1899 fsm.lock.RUnlock() 1900 1901 // under zero means that the context was canceled. 1902 if nextState >= bgp.BGP_FSM_IDLE { 1903 fsm.lock.RLock() 1904 h.stateCh <- &fsmMsg{ 1905 MsgType: fsmMsgStateChange, 1906 MsgSrc: fsm.pConf.State.NeighborAddress, 1907 MsgData: nextState, 1908 StateReason: reason, 1909 Version: h.fsm.version, 1910 } 1911 fsm.lock.RUnlock() 1912 } 1913 return nil 1914 } 1915 1916 func (h *fsmHandler) changeadminState(s adminState) error { 1917 h.fsm.lock.Lock() 1918 defer h.fsm.lock.Unlock() 1919 1920 fsm := h.fsm 1921 if fsm.adminState != s { 1922 log.WithFields(log.Fields{ 1923 "Topic": "Peer", 1924 "Key": fsm.pConf.State.NeighborAddress, 1925 "State": fsm.state.String(), 1926 "adminState": s.String(), 1927 }).Debug("admin state changed") 1928 1929 fsm.adminState = s 1930 fsm.pConf.State.AdminDown = !fsm.pConf.State.AdminDown 1931 1932 switch s { 1933 case adminStateUp: 1934 log.WithFields(log.Fields{ 1935 "Topic": "Peer", 1936 "Key": fsm.pConf.State.NeighborAddress, 1937 "State": fsm.state.String(), 1938 }).Info("Administrative start") 1939 case adminStateDown: 1940 log.WithFields(log.Fields{ 1941 "Topic": "Peer", 1942 "Key": fsm.pConf.State.NeighborAddress, 1943 "State": fsm.state.String(), 1944 }).Info("Administrative shutdown") 1945 case adminStatePfxCt: 1946 log.WithFields(log.Fields{ 1947 "Topic": "Peer", 1948 "Key": fsm.pConf.State.NeighborAddress, 1949 "State": fsm.state.String(), 1950 }).Info("Administrative shutdown(Prefix limit reached)") 1951 } 1952 1953 } else { 1954 log.WithFields(log.Fields{ 1955 "Topic": "Peer", 1956 "Key": fsm.pConf.State.NeighborAddress, 1957 "State": fsm.state.String(), 1958 }).Warn("cannot change to the same state") 1959 1960 return fmt.Errorf("cannot change to the same state.") 1961 } 1962 return nil 1963 }