diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-08-03 04:27:33 +0000 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-04-04 22:07:46 +0900 |
commit | bba54bdaa14c1a4c13245548757b38a89531fd9b (patch) | |
tree | ee8b87c207dc489d64f0a6e55c2bca0ede3f20bf | |
parent | 00f8406cb6a207341ea4f68a8fa294f31eb7bc7b (diff) |
skip asn negotiation for BGP unnumbered peers
since BGP unnumbered peers are typically trusted, skip asn negotiation
for easy configuration.
from configuration file:
```toml
[[neighbors]]
[[neighbors.config]]
neighbor-interface = "eth0"
```
from cli:
```
$ gobgp neighbor add interface eth0
```
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | api/grpc_server.go | 15 | ||||
-rw-r--r-- | config/default.go | 2 | ||||
-rw-r--r-- | gobgp/cmd/monitor.go | 12 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 32 | ||||
-rw-r--r-- | packet/bgp/validate.go | 12 | ||||
-rw-r--r-- | server/fsm.go | 24 | ||||
-rw-r--r-- | server/peer.go | 2 | ||||
-rw-r--r-- | server/server.go | 58 | ||||
-rw-r--r-- | server/server_test.go | 4 | ||||
-rw-r--r-- | table/path.go | 6 |
10 files changed, 105 insertions, 62 deletions
diff --git a/api/grpc_server.go b/api/grpc_server.go index 9fc66bde..33ee13c5 100644 --- a/api/grpc_server.go +++ b/api/grpc_server.go @@ -195,6 +195,8 @@ func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer { Received: s.AdjTable.Received, Accepted: s.AdjTable.Accepted, Advertised: s.AdjTable.Advertised, + PeerAs: s.PeerAs, + PeerType: uint32(s.PeerType.ToInt()), }, Timers: &Timers{ Config: &TimersConfig{ @@ -429,15 +431,16 @@ func (s *Server) MonitorPeerState(arg *Arguments, stream GobgpApi_MonitorPeerSta case ev := <-w.Event(): switch msg := ev.(type) { case *server.WatchEventPeerState: - if len(arg.Name) > 0 && arg.Name != msg.PeerAddress.String() { + if len(arg.Name) > 0 && arg.Name != msg.PeerAddress.String() && arg.Name != msg.PeerInterface { continue } if err := stream.Send(&Peer{ Conf: &PeerConf{ - PeerAs: msg.PeerAS, - LocalAs: msg.LocalAS, - NeighborAddress: msg.PeerAddress.String(), - Id: msg.PeerID.String(), + PeerAs: msg.PeerAS, + LocalAs: msg.LocalAS, + NeighborAddress: msg.PeerAddress.String(), + Id: msg.PeerID.String(), + NeighborInterface: msg.PeerInterface, }, Info: &PeerState{ PeerAs: msg.PeerAS, @@ -961,6 +964,8 @@ func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) { pconf.State.AdjTable.Received = a.Info.Received pconf.State.AdjTable.Accepted = a.Info.Accepted pconf.State.AdjTable.Advertised = a.Info.Advertised + pconf.State.PeerAs = a.Info.PeerAs + pconf.State.PeerType = config.IntToPeerTypeMap[int(a.Info.PeerType)] if a.Info.Messages != nil { if a.Info.Messages.Sent != nil { diff --git a/config/default.go b/config/default.go index 92c743dd..094afb2b 100644 --- a/config/default.go +++ b/config/default.go @@ -105,6 +105,8 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui n.Config.PeerType = PEER_TYPE_INTERNAL } + n.State.PeerAs = n.Config.PeerAs + if !v.IsSet("neighbor.timers.config.connect-retry") && n.Timers.Config.ConnectRetry == 0 { n.Timers.Config.ConnectRetry = float64(DEFAULT_CONNECT_RETRY) } diff --git a/gobgp/cmd/monitor.go b/gobgp/cmd/monitor.go index 8a7866b1..661b6c24 100644 --- a/gobgp/cmd/monitor.go +++ b/gobgp/cmd/monitor.go @@ -74,11 +74,7 @@ func NewMonitorCmd() *cobra.Command { neighborCmd := &cobra.Command{ Use: CMD_NEIGHBOR, Run: func(cmd *cobra.Command, args []string) { - var names []string - if len(args) > 0 { - names = []string{args[0]} - } - stream, err := client.MonitorNeighborState(names...) + stream, err := client.MonitorNeighborState(args...) if err != nil { exitWithError(err) } @@ -93,7 +89,11 @@ func NewMonitorCmd() *cobra.Command { j, _ := json.Marshal(s) fmt.Println(string(j)) } else { - fmt.Printf("[NEIGH] %s fsm: %s admin: %s\n", s.Config.NeighborAddress, s.State.SessionState, s.State.AdminState) + addr := s.Config.NeighborAddress + if s.Config.NeighborInterface != "" { + addr = fmt.Sprintf("%s(%s)", addr, s.Config.NeighborInterface) + } + fmt.Printf("[NEIGH] %s fsm: %s admin: %s\n", addr, s.State.SessionState, s.State.AdminState) } } }, diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 5ab7e32c..b39c1a56 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -53,6 +53,14 @@ func getNeighbor(name string, enableAdvertised bool) (*config.Neighbor, error) { return client.GetNeighbor(name, enableAdvertised) } +func getASN(p *config.Neighbor) string { + asn := "*" + if p.State.PeerAs > 0 { + asn = fmt.Sprint(p.State.PeerAs) + } + return asn +} + func showNeighbors(vrf string) error { m, err := getNeighbors(vrf) if err != nil { @@ -71,7 +79,7 @@ func showNeighbors(vrf string) error { return nil } maxaddrlen := 0 - maxaslen := 0 + maxaslen := 2 maxtimelen := len("Up/Down") timedelta := []string{} @@ -84,8 +92,8 @@ func showNeighbors(vrf string) error { } else if j := len(n.Config.NeighborAddress); j > maxaddrlen { maxaddrlen = j } - if len(fmt.Sprint(n.Config.PeerAs)) > maxaslen { - maxaslen = len(fmt.Sprint(n.Config.PeerAs)) + if l := len(getASN(n)); l > maxaslen { + maxaslen = l } timeStr := "never" if n.Timers.State.Uptime != 0 { @@ -135,7 +143,7 @@ func showNeighbors(vrf string) error { if n.Config.NeighborInterface != "" { neigh = n.Config.NeighborInterface } - fmt.Printf(format, neigh, fmt.Sprint(n.Config.PeerAs), timedelta[i], format_fsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted)) + fmt.Printf(format, neigh, getASN(n), timedelta[i], format_fsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted)) } return nil @@ -152,7 +160,7 @@ func showNeighbor(args []string) error { return nil } - fmt.Printf("BGP neighbor is %s, remote AS %d", p.Config.NeighborAddress, p.Config.PeerAs) + fmt.Printf("BGP neighbor is %s, remote AS %s", p.Config.NeighborAddress, getASN(p)) if p.RouteReflector.Config.RouteReflectorClient { fmt.Printf(", route-reflector-client\n") @@ -311,13 +319,13 @@ func showNeighbor(args []string) error { } return strings.Join(lines, "\n") } - if m := lookup(c, p.Conf.LocalCap); m != nil { + if m := lookup(c, p.State.LocalCapabilityList); m != nil { e := m.(*bgp.CapExtendedNexthop) if s := exnhStr(e); len(s) > 0 { fmt.Printf(" Local: %s\n", s) } } - if m := lookup(c, p.Conf.RemoteCap); m != nil { + if m := lookup(c, p.State.LocalCapabilityList); m != nil { e := m.(*bgp.CapExtendedNexthop) if s := exnhStr(e); len(s) > 0 { fmt.Printf(" Remote: %s\n", s) @@ -849,13 +857,15 @@ func modNeighbor(cmdType string, args []string) error { var err error switch cmdType { case CMD_ADD: - if len(m["as"]) != 1 { + if len(m[""]) > 0 && len(m["as"]) != 1 { return fmt.Errorf("%s", usage) } var as int - as, err = strconv.Atoi(m["as"][0]) - if err != nil { - return err + if len(m["as"]) > 0 { + as, err = strconv.Atoi(m["as"][0]) + if err != nil { + return err + } } err = client.AddNeighbor(getConf(as)) case CMD_DEL: diff --git a/packet/bgp/validate.go b/packet/bgp/validate.go index 5cf2afbb..13c66a77 100644 --- a/packet/bgp/validate.go +++ b/packet/bgp/validate.go @@ -230,9 +230,9 @@ func ValidateBGPMessage(m *BGPMessage) error { return nil } -func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) error { +func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) (uint32, error) { if m.Version != 4 { - return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_VERSION_NUMBER, nil, fmt.Sprintf("upsuppored version %d", m.Version)) + return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_VERSION_NUMBER, nil, fmt.Sprintf("upsuppored version %d", m.Version)) } as := uint32(m.MyAS) @@ -248,12 +248,12 @@ func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) error { } } } - if as != expectedAS { - return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_PEER_AS, nil, fmt.Sprintf("as number mismatch expected %d, received %d", expectedAS, as)) + if expectedAS != 0 && as != expectedAS { + return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_PEER_AS, nil, fmt.Sprintf("as number mismatch expected %d, received %d", expectedAS, as)) } if m.HoldTime < 3 && m.HoldTime != 0 { - return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNACCEPTABLE_HOLD_TIME, nil, fmt.Sprintf("unacceptable hold time %d", m.HoldTime)) + return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNACCEPTABLE_HOLD_TIME, nil, fmt.Sprintf("unacceptable hold time %d", m.HoldTime)) } - return nil + return as, nil } diff --git a/server/fsm.go b/server/fsm.go index e680f8ec..f623f399 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -474,9 +474,9 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) { break } fsm.conn = conn - if fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL { + if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL { ttl := 1 - if fsm.pConf.EbgpMultihop.Config.Enabled == true { + if fsm.pConf.EbgpMultihop.Config.Enabled { ttl = int(fsm.pConf.EbgpMultihop.Config.MultihopTtl) } if ttl != 0 { @@ -844,11 +844,29 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { if m.Header.Type == bgp.BGP_MSG_OPEN { fsm.recvOpen = m body := m.Body.(*bgp.BGPOpen) - err := bgp.ValidateOpenMsg(body, fsm.pConf.Config.PeerAs) + peerAs, err := bgp.ValidateOpenMsg(body, fsm.pConf.Config.PeerAs) if err != nil { fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError)) return bgp.BGP_FSM_IDLE, FSM_INVALID_MSG } + + // ASN negotiation was skipped + if fsm.pConf.Config.PeerAs == 0 { + typ := config.PEER_TYPE_EXTERNAL + if fsm.peerInfo.LocalAS == peerAs { + typ = config.PEER_TYPE_INTERNAL + } + fsm.pConf.State.PeerType = typ + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": fsm.pConf.Config.NeighborAddress, + "State": fsm.state.String(), + }).Infof("skiped asn negotiation: peer-as: %d, peer-type: %s", peerAs, typ) + } else { + fsm.pConf.State.PeerType = fsm.pConf.Config.PeerType + } + fsm.pConf.State.PeerAs = peerAs + fsm.peerInfo.AS = peerAs fsm.peerInfo.ID = body.ID fsm.capMap, fsm.rfMap = open2Cap(body, fsm.pConf) diff --git a/server/peer.go b/server/peer.go index 96e014db..15029bd6 100644 --- a/server/peer.go +++ b/server/peer.go @@ -69,7 +69,7 @@ func (peer *Peer) TableID() string { } func (peer *Peer) isIBGPPeer() bool { - return peer.fsm.pConf.Config.PeerAs == peer.fsm.gConf.Config.As + return peer.fsm.pConf.State.PeerAs == peer.fsm.gConf.Config.As } func (peer *Peer) isRouteServerClient() bool { diff --git a/server/server.go b/server/server.go index 8260e566..5238c33b 100644 --- a/server/server.go +++ b/server/server.go @@ -288,7 +288,7 @@ func sendFsmOutgoingMsg(peer *Peer, paths []*table.Path, notification *bgp.BGPMe func isASLoop(peer *Peer, path *table.Path) bool { for _, as := range path.GetAsList() { - if as == peer.fsm.pConf.Config.PeerAs { + if as == peer.fsm.pConf.State.PeerAs { return true } } @@ -329,7 +329,7 @@ func filterpath(peer *Peer, path, old *table.Path) *table.Path { ignore = true info := path.GetSource() //if the path comes from eBGP peer - if info.AS != peer.fsm.pConf.Config.PeerAs { + if info.AS != peer.fsm.pConf.State.PeerAs { ignore = false } // RFC4456 8. Avoiding Routing Information Loops @@ -509,18 +509,19 @@ func createWatchEventPeerState(peer *Peer) *WatchEventPeerState { sentOpen := buildopen(peer.fsm.gConf, peer.fsm.pConf) recvOpen := peer.fsm.recvOpen return &WatchEventPeerState{ - PeerAS: peer.fsm.peerInfo.AS, - LocalAS: peer.fsm.peerInfo.LocalAS, - PeerAddress: peer.fsm.peerInfo.Address, - LocalAddress: net.ParseIP(laddr), - PeerPort: rport, - LocalPort: lport, - PeerID: peer.fsm.peerInfo.ID, - SentOpen: sentOpen, - RecvOpen: recvOpen, - State: peer.fsm.state, - AdminState: peer.fsm.adminState, - Timestamp: time.Now(), + PeerAS: peer.fsm.peerInfo.AS, + LocalAS: peer.fsm.peerInfo.LocalAS, + PeerAddress: peer.fsm.peerInfo.Address, + LocalAddress: net.ParseIP(laddr), + PeerPort: rport, + LocalPort: lport, + PeerID: peer.fsm.peerInfo.ID, + SentOpen: sentOpen, + RecvOpen: recvOpen, + State: peer.fsm.state, + AdminState: peer.fsm.adminState, + Timestamp: time.Now(), + PeerInterface: peer.fsm.pConf.Config.NeighborInterface, } } @@ -687,6 +688,10 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { peer.prefixLimitWarned = make(map[bgp.RouteFamily]bool) peer.DropAll(drop) server.dropPeerAllRoutes(peer, drop) + if peer.fsm.pConf.Config.PeerAs == 0 { + peer.fsm.pConf.State.PeerAs = 0 + peer.fsm.peerInfo.AS = 0 + } } else if peer.fsm.pConf.GracefulRestart.State.PeerRestarting && nextState == bgp.BGP_FSM_IDLE { if peer.fsm.pConf.GracefulRestart.State.LongLivedEnabled { llgr, no_llgr := peer.llgrFamilies() @@ -2114,18 +2119,19 @@ type WatchEventUpdate struct { } type WatchEventPeerState struct { - PeerAS uint32 - LocalAS uint32 - PeerAddress net.IP - LocalAddress net.IP - PeerPort uint16 - LocalPort uint16 - PeerID net.IP - SentOpen *bgp.BGPMessage - RecvOpen *bgp.BGPMessage - State bgp.FSMState - AdminState AdminState - Timestamp time.Time + PeerAS uint32 + LocalAS uint32 + PeerAddress net.IP + LocalAddress net.IP + PeerPort uint16 + LocalPort uint16 + PeerID net.IP + SentOpen *bgp.BGPMessage + RecvOpen *bgp.BGPMessage + State bgp.FSMState + AdminState AdminState + Timestamp time.Time + PeerInterface string } type WatchEventAdjIn struct { diff --git a/server/server_test.go b/server/server_test.go index 3c343b9e..8f5fcc4d 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -185,9 +185,11 @@ func TestNumGoroutineWithAddDeleteNeighbor(t *testing.T) { } func newPeerandInfo(myAs, as uint32, address string, rib *table.TableManager) (*Peer, *table.PeerInfo) { + nConf := &config.Neighbor{Config: config.NeighborConfig{PeerAs: as, NeighborAddress: address}} + config.SetDefaultNeighborConfigValues(nConf, myAs) p := NewPeer( &config.Global{Config: config.GlobalConfig{As: myAs}}, - &config.Neighbor{Config: config.NeighborConfig{PeerAs: as, NeighborAddress: address}}, + nConf, rib, &table.RoutingPolicy{}) for _, f := range rib.GetRFlist() { diff --git a/table/path.go b/table/path.go index c31d6cc6..b8db56a7 100644 --- a/table/path.go +++ b/table/path.go @@ -181,7 +181,7 @@ func (path *Path) UpdatePathAttrs(global *config.Global, peer *config.Neighbor, return ip.Equal(net.ParseIP("0.0.0.0")) || ip.Equal(net.ParseIP("::")) } nexthop := path.GetNexthop() - if peer.Config.PeerType == config.PEER_TYPE_EXTERNAL { + if peer.State.PeerType == config.PEER_TYPE_EXTERNAL { // NEXTHOP handling if !path.IsLocal() || isZero(nexthop) { path.SetNexthop(localAddress) @@ -195,7 +195,7 @@ func (path *Path) UpdatePathAttrs(global *config.Global, peer *config.Neighbor, path.delPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC) } - } else if peer.Config.PeerType == config.PEER_TYPE_INTERNAL { + } else if peer.State.PeerType == config.PEER_TYPE_INTERNAL { // NEXTHOP handling for iBGP // if the path generated locally set local address as nexthop. // if not, don't modify it. @@ -255,7 +255,7 @@ func (path *Path) UpdatePathAttrs(global *config.Global, peer *config.Neighbor, log.WithFields(log.Fields{ "Topic": "Peer", "Key": peer.Config.NeighborAddress, - }).Warnf("invalid peer type: %d", peer.Config.PeerType) + }).Warnf("invalid peer type: %d", peer.State.PeerType) } } |