diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/fsm.go | 20 | ||||
-rw-r--r-- | server/peer.go | 48 | ||||
-rw-r--r-- | server/server.go | 60 |
3 files changed, 101 insertions, 27 deletions
diff --git a/server/fsm.go b/server/fsm.go index 849d8169..76ed85a6 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -110,11 +110,19 @@ func (fsm *FSM) PeerInfoGet() *table.PeerInfo { } func (fsm *FSM) createPeerInfo() { + var rf table.RouteFamily + if fsm.peerConfig.NeighborAddress.To4() != nil { + rf = table.RF_IPv4_UC + } else { + rf = table.RF_IPv6_UC + } + fsm.peerInfo = &table.PeerInfo{ AS: fsm.peerConfig.PeerAs, ID: fsm.routerId, VersionNum: fsm.sourceVerNum, LocalID: fsm.globalConfig.RouterId, + RF: rf, } } @@ -168,14 +176,20 @@ func (h *FSMHandler) active() bgp.FSMState { return bgp.BGP_FSM_OPENSENT } -func buildopen(global *config.GlobalType, neighborT *config.NeighborType) *bgp.BGPMessage { +func buildopen(global *config.GlobalType, peerConf *config.NeighborType) *bgp.BGPMessage { + var afi int + if peerConf.NeighborAddress.To4() != nil { + afi = bgp.AFI_IP + } else { + afi = bgp.AFI_IP6 + } p1 := bgp.NewOptionParameterCapability( []bgp.ParameterCapabilityInterface{bgp.NewCapRouteRefresh()}) p2 := bgp.NewOptionParameterCapability( - []bgp.ParameterCapabilityInterface{bgp.NewCapMultiProtocol(bgp.AFI_IP, bgp.SAFI_UNICAST)}) + []bgp.ParameterCapabilityInterface{bgp.NewCapMultiProtocol(uint16(afi), bgp.SAFI_UNICAST)}) p3 := bgp.NewOptionParameterCapability( []bgp.ParameterCapabilityInterface{bgp.NewCapFourOctetASNumber(global.As)}) - holdTime := uint16(neighborT.Timers.HoldTime) + holdTime := uint16(peerConf.Timers.HoldTime) as := global.As if as > (1<<16)-1 { as = bgp.AS_TRANS diff --git a/server/peer.go b/server/peer.go index b3261dbd..fd36ce09 100644 --- a/server/peer.go +++ b/server/peer.go @@ -41,6 +41,8 @@ type Peer struct { // peer and rib are always not one-to-one so should not be // here but it's the simplest and works our first target. rib *table.TableManager + // for now we support only the same afi as transport + rf table.RouteFamily } func NewPeer(g config.GlobalType, peer config.NeighborType, outEventCh chan *message) *Peer { @@ -55,6 +57,11 @@ func NewPeer(g config.GlobalType, peer config.NeighborType, outEventCh chan *mes } p.fsm = NewFSM(&g, &peer, p.acceptedConnCh, p.incoming, p.outgoing) peer.BgpNeighborCommonState.State = uint32(bgp.BGP_FSM_IDLE) + if peer.NeighborAddress.To4() != nil { + p.rf = table.RF_IPv4_UC + } else { + p.rf = table.RF_IPv6_UC + } p.adjRib = table.NewAdjRib() p.rib = table.NewTableManager() p.t.Go(p.loop) @@ -67,7 +74,7 @@ func (peer *Peer) handleBGPmessage(m *bgp.BGPMessage) { switch m.Header.Type { case bgp.BGP_MSG_ROUTE_REFRESH: - pathList := peer.adjRib.GetOutPathList(table.RF_IPv4_UC) + pathList := peer.adjRib.GetOutPathList(peer.rf) peer.sendMessages(peer.path2update(pathList)) case bgp.BGP_MSG_UPDATE: peer.peerConfig.BgpNeighborCommonState.UpdateRecvTime = time.Now() @@ -87,18 +94,40 @@ func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) { } } +func path2v4update(path table.Path) *bgp.BGPMessage { + if path.IsWithdraw() { + draw := path.GetNlri().(*bgp.WithdrawnRoute) + return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{*draw}, []bgp.PathAttributeInterface{}, []bgp.NLRInfo{}) + } else { + nlri := path.GetNlri().(*bgp.NLRInfo) + pathAttrs := path.GetPathAttrs() + return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{*nlri}) + } +} + +func path2v6update(path table.Path) *bgp.BGPMessage { + if path.IsWithdraw() { + pathAttrs := path.GetPathAttrs() + return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{}) + } else { + pathAttrs := path.GetPathAttrs() + return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{}) + } +} + func (peer *Peer) path2update(pathList []table.Path) []*bgp.BGPMessage { // TODO: merge multiple messages // TODO: 4bytes and 2bytes conversion. msgs := make([]*bgp.BGPMessage, 0) for _, p := range pathList { - if p.IsWithdraw() { - draw := p.GetNlri().(*bgp.WithdrawnRoute) - msgs = append(msgs, bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{*draw}, []bgp.PathAttributeInterface{}, []bgp.NLRInfo{})) + if peer.rf != p.GetRouteFamily() { + continue + } + + if peer.rf == table.RF_IPv4_UC { + msgs = append(msgs, path2v4update(p)) } else { - pathAttrs := p.GetPathAttrs() - nlri := p.GetNlri().(*bgp.NLRInfo) - msgs = append(msgs, bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{*nlri})) + msgs = append(msgs, path2v6update(p)) } } return msgs @@ -106,7 +135,7 @@ func (peer *Peer) path2update(pathList []table.Path) []*bgp.BGPMessage { func (peer *Peer) handleREST(restReq *api.RestRequest) { result := &api.RestResponse{} - j, _ := json.Marshal(peer.rib.Tables[bgp.RF_IPv4_UC]) + j, _ := json.Marshal(peer.rib.Tables[peer.rf]) result.Data = j restReq.ResponseCh <- result close(restReq.ResponseCh) @@ -151,9 +180,8 @@ func (peer *Peer) loop() error { peer.peerConfig.BgpNeighborCommonState.State = uint32(nextState) peer.fsm.StateChange(nextState) sameState = false - // TODO: check peer's rf if nextState == bgp.BGP_FSM_ESTABLISHED { - pathList := peer.adjRib.GetOutPathList(table.RF_IPv4_UC) + pathList := peer.adjRib.GetOutPathList(peer.rf) peer.sendMessages(peer.path2update(pathList)) peer.fsm.peerConfig.BgpNeighborCommonState.Uptime = time.Now() peer.fsm.peerConfig.BgpNeighborCommonState.EstablishedCount++ diff --git a/server/server.go b/server/server.go index e97d31c4..99ea974c 100644 --- a/server/server.go +++ b/server/server.go @@ -62,37 +62,67 @@ func NewBgpServer(port int) *BgpServer { return &b } -func (server *BgpServer) Serve() { - server.bgpConfig.Global = <-server.globalTypeCh - - service := ":" + strconv.Itoa(server.listenPort) - addr, _ := net.ResolveTCPAddr("tcp", service) +// avoid mapped IPv6 address +func listenAndAccept(proto string, port int, ch chan *net.TCPConn) (*net.TCPListener, error) { + service := ":" + strconv.Itoa(port) + addr, _ := net.ResolveTCPAddr(proto, service) - l, err := net.ListenTCP("tcp4", addr) + l, err := net.ListenTCP(proto, addr) if err != nil { - log.Fatal(err) - os.Exit(1) + log.Info(err) + return nil, err } - - acceptCh := make(chan *net.TCPConn) go func() { for { - conn, err := l.Accept() + conn, err := l.AcceptTCP() if err != nil { log.Info(err) continue } - acceptCh <- conn.(*net.TCPConn) + ch <- conn } }() + return l, nil +} + +func (server *BgpServer) Serve() { + server.bgpConfig.Global = <-server.globalTypeCh + + listenerMap := make(map[string]*net.TCPListener) + acceptCh := make(chan *net.TCPConn) + l4, err1 := listenAndAccept("tcp4", server.listenPort, acceptCh) + listenerMap["tcp4"] = l4 + l6, err2 := listenAndAccept("tcp6", server.listenPort, acceptCh) + listenerMap["tcp6"] = l6 + if err1 != nil && err2 != nil { + log.Fatal("can't listen either v4 and v6") + os.Exit(1) + } + + listenFile := func(addr net.IP) *os.File { + var l *net.TCPListener + if addr.To4() != nil { + l = listenerMap["tcp4"] + } else { + l = listenerMap["tcp6"] + } + f, _ := l.File() + return f + } + server.peerMap = make(map[string]*Peer) broadcastCh := make(chan *message) for { - f, _ := l.File() select { case conn := <-acceptCh: - remoteAddr := strings.Split(conn.RemoteAddr().String(), ":")[0] + remoteAddr := func(addrPort string) string { + if strings.Index(addrPort, "[") == -1 { + return strings.Split(addrPort, ":")[0] + } + idx := strings.LastIndex(addrPort, ":") + return addrPort[1 : idx-1] + }(conn.RemoteAddr().String()) peer, found := server.peerMap[remoteAddr] if found { log.Info("accepted a new passive connection from ", remoteAddr) @@ -103,11 +133,13 @@ func (server *BgpServer) Serve() { } case peer := <-server.addedPeerCh: addr := peer.NeighborAddress.String() + f := listenFile(peer.NeighborAddress) SetTcpMD5SigSockopts(int(f.Fd()), addr, peer.AuthPassword) p := NewPeer(server.bgpConfig.Global, peer, broadcastCh) server.peerMap[peer.NeighborAddress.String()] = p case peer := <-server.deletedPeerCh: addr := peer.NeighborAddress.String() + f := listenFile(peer.NeighborAddress) SetTcpMD5SigSockopts(int(f.Fd()), addr, "") p, found := server.peerMap[addr] if found { |