summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/peer.go39
-rw-r--r--table/message.go99
2 files changed, 104 insertions, 34 deletions
diff --git a/server/peer.go b/server/peer.go
index 8379d079..35fc3d90 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -89,7 +89,7 @@ func (peer *Peer) handleBGPmessage(m *bgp.BGPMessage) {
case bgp.BGP_MSG_ROUTE_REFRESH:
pathList := peer.adjRib.GetOutPathList(peer.rf)
- peer.sendMessages(peer.path2update(pathList))
+ peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList))
case bgp.BGP_MSG_UPDATE:
peer.peerConfig.BgpNeighborCommonState.UpdateRecvTime = time.Now()
body := m.Body.(*bgp.BGPUpdate)
@@ -106,31 +106,24 @@ func (peer *Peer) handleBGPmessage(m *bgp.BGPMessage) {
func (peer *Peer) sendMessages(msgs []*bgp.BGPMessage) {
for _, m := range msgs {
- if m.Header.Type == bgp.BGP_MSG_UPDATE {
- _, y := peer.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER]
- if !y {
- log.Debug("update BGPUpdate for 2byte AS peer, ", peer.peerConfig.NeighborAddress.String())
- table.UpdatePathAttrs2ByteAs(m.Body.(*bgp.BGPUpdate))
- }
+ // FIXME: there is race where state change
+ // (established) event arrived before open message
+ if peer.peerConfig.BgpNeighborCommonState.State != uint32(bgp.BGP_FSM_ESTABLISHED) {
+ continue
}
- peer.outgoing <- m
- }
-}
-func (peer *Peer) path2update(pathList []table.Path) []*bgp.BGPMessage {
- msgs := make([]*bgp.BGPMessage, 0)
- var pMsg *bgp.BGPMessage
- for _, p := range pathList {
- if peer.rf != p.GetRouteFamily() {
- continue
+ if m.Header.Type != bgp.BGP_MSG_UPDATE {
+ log.Fatal("not update message ", m.Header.Type)
}
- msg, _ := table.CreateUpdateMsgFromPath(p, pMsg)
- if msg != nil {
- msgs = append(msgs, msg)
- pMsg = msg
+
+ _, y := peer.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER]
+ if !y {
+ log.Debug("update BGPUpdate for 2byte AS peer, ", peer.peerConfig.NeighborAddress.String())
+ table.UpdatePathAttrs2ByteAs(m.Body.(*bgp.BGPUpdate))
}
+
+ peer.outgoing <- m
}
- return msgs
}
func (peer *Peer) handleREST(restReq *api.RestRequest) {
@@ -152,7 +145,7 @@ func (peer *Peer) handlePeermessage(m *message) {
}
}
peer.adjRib.UpdateOut(pathList)
- peer.sendMessages(peer.path2update(pathList))
+ peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList))
}
switch m.event {
@@ -183,7 +176,7 @@ func (peer *Peer) loop() error {
sameState = false
if nextState == bgp.BGP_FSM_ESTABLISHED {
pathList := peer.adjRib.GetOutPathList(peer.rf)
- peer.sendMessages(peer.path2update(pathList))
+ peer.sendMessages(table.CreateUpdateMsgFromPaths(pathList))
peer.fsm.peerConfig.BgpNeighborCommonState.Uptime = time.Now()
peer.fsm.peerConfig.BgpNeighborCommonState.EstablishedCount++
}
diff --git a/table/message.go b/table/message.go
index 0cfa07e8..b3f730a3 100644
--- a/table/message.go
+++ b/table/message.go
@@ -16,11 +16,13 @@
package table
import (
+ "bytes"
"github.com/osrg/gobgp/packet"
"reflect"
)
func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error {
+ // FIXME: clone
var asAttr *bgp.PathAttributeAsPath
for _, attr := range msg.PathAttributes {
switch attr.(type) {
@@ -129,28 +131,103 @@ func clonePathAttributes(attrs []bgp.PathAttributeInterface) []bgp.PathAttribute
return clonedAttrs
}
-func CreateUpdateMsgFromPath(path Path, msg *bgp.BGPMessage) (*bgp.BGPMessage, error) {
+func createUpdateMsgFromPath(path Path, msg *bgp.BGPMessage) *bgp.BGPMessage {
rf := path.GetRouteFamily()
if rf == bgp.RF_IPv4_UC {
if path.IsWithdraw() {
draw := path.getNlri().(*bgp.WithdrawnRoute)
- return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{*draw}, []bgp.PathAttributeInterface{}, []bgp.NLRInfo{}), nil
+ if msg != nil {
+ u := msg.Body.(*bgp.BGPUpdate)
+ u.WithdrawnRoutes = append(u.WithdrawnRoutes, *draw)
+ return nil
+ } else {
+ 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}), nil
+ if msg != nil {
+ u := msg.Body.(*bgp.BGPUpdate)
+ u.NLRI = append(u.NLRI, *nlri)
+ } else {
+ pathAttrs := path.getPathAttrs()
+ return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{*nlri})
+ }
}
} else if rf == bgp.RF_IPv6_UC {
if path.IsWithdraw() {
- clonedAttrs := clonePathAttributes(path.getPathAttrs())
- idx, attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
- reach := attr.(*bgp.PathAttributeMpReachNLRI)
- clonedAttrs[idx] = bgp.NewPathAttributeMpUnreachNLRI(reach.Value)
- return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, clonedAttrs, []bgp.NLRInfo{}), nil
+ if msg != nil {
+ idx, _ := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
+ u := msg.Body.(*bgp.BGPUpdate)
+ unreach := u.PathAttributes[idx].(*bgp.PathAttributeMpUnreachNLRI)
+ unreach.Value = append(unreach.Value, path.getNlri())
+ } else {
+ clonedAttrs := clonePathAttributes(path.getPathAttrs())
+ idx, attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
+ reach := attr.(*bgp.PathAttributeMpReachNLRI)
+ clonedAttrs[idx] = bgp.NewPathAttributeMpUnreachNLRI(reach.Value)
+ return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, clonedAttrs, []bgp.NLRInfo{})
+ }
+ } else {
+ if msg != nil {
+ idx, _ := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
+ u := msg.Body.(*bgp.BGPUpdate)
+ reachAttr := u.PathAttributes[idx].(*bgp.PathAttributeMpReachNLRI)
+ reachAttr.Value = append(reachAttr.Value, path.getNlri())
+ } else {
+ // we don't need to clone here but we
+ // might merge path to this message in
+ // the future so let's clone anyway.
+ clonedAttrs := clonePathAttributes(path.getPathAttrs())
+ return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, clonedAttrs, []bgp.NLRInfo{})
+ }
+ }
+ }
+ return nil
+}
+
+func isSamePathAttrs(pList1 []bgp.PathAttributeInterface, pList2 []bgp.PathAttributeInterface) bool {
+ if len(pList1) != len(pList2) {
+ return false
+ }
+ for i, p1 := range pList1 {
+ _, y := p1.(*bgp.PathAttributeMpReachNLRI)
+ if y {
+ continue
+ }
+ b1, _ := p1.Serialize()
+ b2, _ := pList2[i].Serialize()
+
+ if bytes.Compare(b1, b2) != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+func isMergeable(p1 Path, p2 Path) bool {
+ if p1 == nil {
+ return false
+ }
+ if p1.getSource() == p2.getSource() && isSamePathAttrs(p1.getPathAttrs(), p2.getPathAttrs()) {
+ return true
+ }
+ return false
+}
+
+func CreateUpdateMsgFromPaths(pathList []Path) []*bgp.BGPMessage {
+ var pre Path
+ var msgs []*bgp.BGPMessage
+ for _, path := range pathList {
+ y := isMergeable(pre, path)
+ if y {
+ msg := msgs[len(msgs)-1]
+ createUpdateMsgFromPath(path, msg)
} else {
- return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, path.getPathAttrs(), []bgp.NLRInfo{}), nil
+ msg := createUpdateMsgFromPath(path, nil)
+ pre = path
+ msgs = append(msgs, msg)
}
}
- return nil, nil
+ return msgs
}