summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/mrt.go69
1 files changed, 55 insertions, 14 deletions
diff --git a/server/mrt.go b/server/mrt.go
index b640dacc..fe61f7a1 100644
--- a/server/mrt.go
+++ b/server/mrt.go
@@ -88,28 +88,41 @@ func (m *mrtWriter) loop() error {
msg := make([]*mrt.MRTMessage, 0, 1)
switch e := ev.(type) {
case *WatchEventUpdate:
- subtype := mrt.MESSAGE_AS4
mp := mrt.NewBGP4MPMessage(e.PeerAS, e.LocalAS, 0, e.PeerAddress.String(), e.LocalAddress.String(), e.FourBytesAs, nil)
mp.BGPMessagePayload = e.Payload
- if e.FourBytesAs == false {
- subtype = mrt.MESSAGE
+ isAddPath := e.Neighbor.IsAddPathReceiveEnabled(e.PathList[0].GetRouteFamily())
+ subtype := mrt.MESSAGE
+ switch {
+ case isAddPath && e.FourBytesAs:
+ subtype = mrt.MESSAGE_AS4_ADDPATH
+ case isAddPath:
+ subtype = mrt.MESSAGE_ADDPATH
+ case e.FourBytesAs:
+ subtype = mrt.MESSAGE_AS4
}
if bm, err := mrt.NewMRTMessage(uint32(e.Timestamp.Unix()), mrt.BGP4MP, subtype, mp); err != nil {
log.WithFields(log.Fields{
"Topic": "mrt",
"Data": e,
"Error": err,
- }).Warn("Failed to create MRT message in serialize()")
+ }).Warnf("Failed to create MRT BGP4MP message (subtype %d)", subtype)
} else {
msg = append(msg, bm)
}
case *WatchEventTable:
t := uint32(time.Now().Unix())
peers := make([]*mrt.Peer, 0, len(e.Neighbor))
+ neighborMap := make(map[string]*config.Neighbor)
for _, pconf := range e.Neighbor {
peers = append(peers, mrt.NewPeer(pconf.State.RemoteRouterId, pconf.State.NeighborAddress, pconf.Config.PeerAs, true))
+ neighborMap[pconf.State.NeighborAddress] = pconf
}
if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, mrt.PEER_INDEX_TABLE, mrt.NewPeerIndexTable(e.RouterId, "", peers)); err != nil {
+ log.WithFields(log.Fields{
+ "Topic": "mrt",
+ "Data": e,
+ "Error": err,
+ }).Warnf("Failed to create MRT TABLE_DUMPv2 message (subtype %d)", mrt.PEER_INDEX_TABLE)
break
} else {
msg = append(msg, bm)
@@ -124,33 +137,61 @@ func (m *mrtWriter) loop() error {
return uint16(len(e.Neighbor))
}
- subtype := func(p *table.Path) mrt.MRTSubTypeTableDumpv2 {
+ subtype := func(p *table.Path, isAddPath bool) mrt.MRTSubTypeTableDumpv2 {
+ t := mrt.RIB_GENERIC
switch p.GetRouteFamily() {
case bgp.RF_IPv4_UC:
- return mrt.RIB_IPV4_UNICAST
+ t = mrt.RIB_IPV4_UNICAST
case bgp.RF_IPv4_MC:
- return mrt.RIB_IPV4_MULTICAST
+ t = mrt.RIB_IPV4_MULTICAST
case bgp.RF_IPv6_UC:
- return mrt.RIB_IPV6_UNICAST
+ t = mrt.RIB_IPV6_UNICAST
case bgp.RF_IPv6_MC:
- return mrt.RIB_IPV6_MULTICAST
+ t = mrt.RIB_IPV6_MULTICAST
+ }
+ if isAddPath {
+ // Shift non-additional-path version to *_ADDPATH
+ t += 6
}
- return mrt.RIB_GENERIC
+ return t
}
seq := uint32(0)
+ appendTableDumpMsg := func(path *table.Path, entries []*mrt.RibEntry, isAddPath bool) {
+ st := subtype(path, isAddPath)
+ if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, st, mrt.NewRib(seq, path.GetNlri(), entries)); err != nil {
+ log.WithFields(log.Fields{
+ "Topic": "mrt",
+ "Data": e,
+ "Error": err,
+ }).Warnf("Failed to create MRT TABLE_DUMPv2 message (subtype %d)", st)
+ } else {
+ msg = append(msg, bm)
+ seq++
+ }
+ }
for _, pathList := range e.PathList {
entries := make([]*mrt.RibEntry, 0, len(pathList))
+ entriesAddPath := make([]*mrt.RibEntry, 0, len(pathList))
for _, path := range pathList {
if path.IsLocal() {
continue
}
- entries = append(entries, mrt.NewRibEntry(idx(path), uint32(path.GetTimestamp().Unix()), 0, path.GetPathAttrs()))
+ isAddPath := false
+ if neighbor, ok := neighborMap[path.GetSource().Address.String()]; ok {
+ isAddPath = neighbor.IsAddPathReceiveEnabled(path.GetRouteFamily())
+ }
+ if !isAddPath {
+ entries = append(entries, mrt.NewRibEntry(idx(path), uint32(path.GetTimestamp().Unix()), 0, path.GetPathAttrs(), false))
+ } else {
+ entriesAddPath = append(entriesAddPath, mrt.NewRibEntry(idx(path), uint32(path.GetTimestamp().Unix()), path.GetNlri().PathIdentifier(), path.GetPathAttrs(), true))
+ }
}
if len(entries) > 0 {
- bm, _ := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, subtype(pathList[0]), mrt.NewRib(seq, pathList[0].GetNlri(), entries))
- msg = append(msg, bm)
- seq++
+ appendTableDumpMsg(pathList[0], entries, false)
+ }
+ if len(entriesAddPath) > 0 {
+ appendTableDumpMsg(pathList[0], entriesAddPath, true)
}
}
}