From fd89ee0f967d57e9afc57daea5d009d361352ec1 Mon Sep 17 00:00:00 2001
From: Oliver Herms <oliver.herms@exaring.de>
Date: Thu, 21 Jun 2018 17:07:56 +0200
Subject: [PATCH] Fixing AS path change on propagation

---
 main.go                                       | 21 +++++++++++++++++--
 protocols/bgp/server/fsm_established.go       |  6 ++++--
 protocols/bgp/server/update_helper.go         |  4 ++--
 protocols/bgp/server/update_sender.go         |  2 +-
 .../bgp/server/update_sender_add_path.go      |  2 +-
 routingtable/adjRIBOut/adj_rib_out.go         |  5 +++++
 .../adjRIBOutAddPath/adj_rib_out_add_path.go  |  5 +++++
 routingtable/neighbor.go                      |  3 +++
 8 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/main.go b/main.go
index ae2b9ba8..7a114f25 100644
--- a/main.go
+++ b/main.go
@@ -10,11 +10,19 @@ import (
 
 	"github.com/bio-routing/bio-rd/config"
 	"github.com/bio-routing/bio-rd/protocols/bgp/server"
+	"github.com/bio-routing/bio-rd/route"
 	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/bio-routing/bio-rd/routingtable/filter"
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
+
+	bnet "github.com/bio-routing/bio-rd/net"
 )
 
+func strAddr(s string) uint32 {
+	ret, _ := bnet.StrToAddr(s)
+	return ret
+}
+
 func main() {
 	logrus.Printf("This is a BGP speaker\n")
 
@@ -32,6 +40,15 @@ func main() {
 		logrus.Fatalf("Unable to start BGP server: %v", err)
 	}
 
+	rib.AddPath(bnet.NewPfx(strAddr("10.0.0.0"), 8), &route.Path{
+		Type: route.BGPPathType,
+		BGPPath: &route.BGPPath{
+			NextHop: 100,
+			ASPath:  "3320",
+			Origin:  1,
+		},
+	})
+
 	b.AddPeer(config.Peer{
 		AdminEnabled:      true,
 		LocalAS:           65200,
@@ -50,7 +67,7 @@ func main() {
 		ExportFilter: filter.NewAcceptAllFilter(),
 	}, rib)
 
-	b.AddPeer(config.Peer{
+	/*b.AddPeer(config.Peer{
 		AdminEnabled:      true,
 		LocalAS:           65200,
 		PeerAS:            65100,
@@ -67,7 +84,7 @@ func main() {
 		AddPathRecv:  true,
 		ImportFilter: filter.NewAcceptAllFilter(),
 		ExportFilter: filter.NewDrainFilter(),
-	}, rib)
+	}, rib)*/
 
 	go func() {
 		for {
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index f1195dad..ca68aecc 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -58,8 +58,10 @@ func (s *establishedState) init() {
 	s.fsm.adjRIBIn.Register(s.fsm.peer.importFilter)
 
 	n := &routingtable.Neighbor{
-		Type:    route.BGPPathType,
-		Address: tnet.IPv4ToUint32(s.fsm.peer.addr),
+		Type:     route.BGPPathType,
+		Address:  tnet.IPv4ToUint32(s.fsm.peer.addr),
+		IBGP:     s.fsm.peer.localASN == s.fsm.peer.peerASN,
+		LocalASN: s.fsm.peer.localASN,
 	}
 
 	clientOptions := routingtable.ClientOptions{}
diff --git a/protocols/bgp/server/update_helper.go b/protocols/bgp/server/update_helper.go
index fdb73fee..e0a24a6e 100644
--- a/protocols/bgp/server/update_helper.go
+++ b/protocols/bgp/server/update_helper.go
@@ -10,8 +10,8 @@ import (
 	log "github.com/sirupsen/logrus"
 )
 
-func pathAttribues(p *route.Path, fsm *FSM) (*packet.PathAttribute, error) {
-	asPathPA, err := packet.ParseASPathStr(strings.TrimRight(fmt.Sprintf("%d %s", fsm.peer.localASN, p.BGPPath.ASPath), " "))
+func pathAttribues(p *route.Path) (*packet.PathAttribute, error) {
+	asPathPA, err := packet.ParseASPathStr(strings.TrimRight(p.BGPPath.ASPath, " "))
 	if err != nil {
 		return nil, fmt.Errorf("Unable to parse AS path: %v", err)
 	}
diff --git a/protocols/bgp/server/update_sender.go b/protocols/bgp/server/update_sender.go
index 76c4eadc..67fb6662 100644
--- a/protocols/bgp/server/update_sender.go
+++ b/protocols/bgp/server/update_sender.go
@@ -28,7 +28,7 @@ func newUpdateSender(fsm *FSM) *UpdateSender {
 
 // AddPath serializes a new path and sends out a BGP update message
 func (u *UpdateSender) AddPath(pfx net.Prefix, p *route.Path) error {
-	pathAttrs, err := pathAttribues(p, u.fsm)
+	pathAttrs, err := pathAttribues(p)
 	if err != nil {
 		log.Errorf("Unable to create BGP Update: %v", err)
 		return nil
diff --git a/protocols/bgp/server/update_sender_add_path.go b/protocols/bgp/server/update_sender_add_path.go
index 0dac8013..7abef161 100644
--- a/protocols/bgp/server/update_sender_add_path.go
+++ b/protocols/bgp/server/update_sender_add_path.go
@@ -25,7 +25,7 @@ func newUpdateSenderAddPath(fsm *FSM) *UpdateSenderAddPath {
 
 // AddPath serializes a new path and sends out a BGP update message
 func (u *UpdateSenderAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
-	pathAttrs, err := pathAttribues(p, u.fsm)
+	pathAttrs, err := pathAttribues(p)
 
 	if err != nil {
 		log.Errorf("Unable to create BGP Update: %v", err)
diff --git a/routingtable/adjRIBOut/adj_rib_out.go b/routingtable/adjRIBOut/adj_rib_out.go
index fe728f0e..5c15e446 100644
--- a/routingtable/adjRIBOut/adj_rib_out.go
+++ b/routingtable/adjRIBOut/adj_rib_out.go
@@ -39,6 +39,11 @@ func (a *AdjRIBOut) AddPath(pfx net.Prefix, p *route.Path) error {
 		return nil
 	}
 
+	p = p.Copy()
+	if !a.neighbor.IBGP {
+		p.BGPPath.ASPath = fmt.Sprintf("%d %s", a.neighbor.LocalASN, p.BGPPath.ASPath)
+	}
+
 	a.mu.Lock()
 	defer a.mu.Unlock()
 
diff --git a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
index f0c75c0b..30c20c4b 100644
--- a/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
+++ b/routingtable/adjRIBOutAddPath/adj_rib_out_add_path.go
@@ -41,6 +41,11 @@ func (a *AdjRIBOutAddPath) AddPath(pfx net.Prefix, p *route.Path) error {
 		return nil
 	}
 
+	p = p.Copy()
+	if !a.neighbor.IBGP {
+		p.BGPPath.ASPath = fmt.Sprintf("%d %s", a.neighbor.LocalASN, p.BGPPath.ASPath)
+	}
+
 	a.mu.Lock()
 	defer a.mu.Unlock()
 
diff --git a/routingtable/neighbor.go b/routingtable/neighbor.go
index 7ae0f739..11b8c8de 100644
--- a/routingtable/neighbor.go
+++ b/routingtable/neighbor.go
@@ -10,4 +10,7 @@ type Neighbor struct {
 
 	// IBGP returns if local ASN is equal to remote ASN
 	IBGP bool
+
+	// Local ASN of session
+	LocalASN uint32
 }
-- 
GitLab