summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/fsm.go20
-rw-r--r--server/peer.go48
-rw-r--r--server/server.go60
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 {