summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-07-31 16:31:50 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-07-31 16:31:50 +0900
commit55f473d7fe07a72dbddcc424d4d6bce76e609e1b (patch)
tree51c2072eeeb201037515bebca4b469a7bc9b13ce
parent848dcec1f7bfc8313c1bc88bbd11be4167fe624a (diff)
gobgp: support mrt injecting only best paths
$ gobgp mrt inject global --only-best your-mrt-dump-file Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--gobgp/cmd/common.go1
-rw-r--r--gobgp/cmd/mrt.go76
-rw-r--r--table/destination.go4
-rw-r--r--table/destination_test.go38
-rw-r--r--table/table.go6
5 files changed, 83 insertions, 42 deletions
diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go
index 49dbf763..e8501f22 100644
--- a/gobgp/cmd/common.go
+++ b/gobgp/cmd/common.go
@@ -102,6 +102,7 @@ var actionOpts struct {
var mrtOpts struct {
OutputDir string
FileFormat string
+ Best bool `long:"only-best" description:"only keep best path routes"`
}
func formatTimedelta(d int64) string {
diff --git a/gobgp/cmd/mrt.go b/gobgp/cmd/mrt.go
index f9287f77..f92db025 100644
--- a/gobgp/cmd/mrt.go
+++ b/gobgp/cmd/mrt.go
@@ -20,14 +20,16 @@ import (
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/packet/bgp"
"github.com/osrg/gobgp/packet/mrt"
+ "github.com/osrg/gobgp/table"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"io"
"os"
"strconv"
+ "time"
)
-func injectMrt(r string, filename string, count int, skip int) error {
+func injectMrt(r string, filename string, count int, skip int, onlyBest bool) error {
var resource api.Resource
switch r {
@@ -110,26 +112,63 @@ func injectMrt(r string, filename string, count int, skip int) error {
exitWithError(fmt.Errorf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers)))
}
- path := &api.Path{
- Pattrs: make([][]byte, 0),
- NoImplicitWithdraw: true,
- SourceAsn: peers[e.PeerIndex].AS,
- SourceId: peers[e.PeerIndex].BgpId.String(),
- }
+ if !onlyBest {
+ path := &api.Path{
+ Pattrs: make([][]byte, 0),
+ NoImplicitWithdraw: true,
+ SourceAsn: peers[e.PeerIndex].AS,
+ SourceId: peers[e.PeerIndex].BgpId.String(),
+ }
- if rf == bgp.RF_IPv4_UC {
- path.Nlri, _ = nlri.Serialize()
- }
+ if rf == bgp.RF_IPv4_UC {
+ path.Nlri, _ = nlri.Serialize()
+ }
- for _, p := range e.PathAttributes {
- b, err := p.Serialize()
- if err != nil {
- continue
+ for _, p := range e.PathAttributes {
+ b, err := p.Serialize()
+ if err != nil {
+ continue
+ }
+ path.Pattrs = append(path.Pattrs, b)
}
- path.Pattrs = append(path.Pattrs, b)
- }
- paths = append(paths, path)
+ paths = append(paths, path)
+ }
+ }
+ if onlyBest {
+ paths = func() []*api.Path {
+ dst := table.NewDestination(nlri)
+ pathList := make([]*table.Path, 0, len(rib.Entries))
+ for _, e := range rib.Entries {
+ p := table.NewPath(&table.PeerInfo{AS: peers[e.PeerIndex].AS, ID: peers[e.PeerIndex].BgpId}, nlri, false, e.PathAttributes, time.Unix(int64(e.OriginatedTime), 0), false)
+ dst.AddNewPath(p)
+ pathList = append(pathList, p)
+ }
+ best, _, _ := dst.Calculate([]string{table.GLOBAL_RIB_NAME})
+ for _, p := range pathList {
+ if p == best[table.GLOBAL_RIB_NAME] {
+ nb, _ := nlri.Serialize()
+ return []*api.Path{&api.Path{
+ Nlri: nb,
+ NoImplicitWithdraw: true,
+ SourceAsn: p.GetSource().AS,
+ SourceId: p.GetSource().ID.String(),
+ Pattrs: func() [][]byte {
+ attrs := make([][]byte, 0)
+ for _, a := range p.GetPathAttrs() {
+ if b, e := a.Serialize(); e == nil {
+
+ attrs = append(attrs, b)
+ }
+ }
+ return attrs
+ }(),
+ }}
+ }
+ }
+ exitWithError(fmt.Errorf("Can't find the best %v", nlri))
+ return []*api.Path{}
+ }()
}
if idx >= skip {
@@ -191,7 +230,7 @@ func NewMrtCmd() *cobra.Command {
}
}
}
- err := injectMrt(CMD_GLOBAL, filename, count, skip)
+ err := injectMrt(CMD_GLOBAL, filename, count, skip, mrtOpts.Best)
if err != nil {
exitWithError(err)
}
@@ -208,5 +247,6 @@ func NewMrtCmd() *cobra.Command {
}
mrtCmd.AddCommand(injectCmd)
+ mrtCmd.PersistentFlags().BoolVarP(&mrtOpts.Best, "only-best", "", false, "inject only best paths")
return mrtCmd
}
diff --git a/table/destination.go b/table/destination.go
index f5bd2c34..d4c24fa2 100644
--- a/table/destination.go
+++ b/table/destination.go
@@ -177,12 +177,12 @@ func (dd *Destination) GetBestPath(id string) *Path {
return nil
}
-func (dd *Destination) addWithdraw(withdraw *Path) {
+func (dd *Destination) AddWithdraw(withdraw *Path) {
dd.validatePath(withdraw)
dd.withdrawList = append(dd.withdrawList, withdraw)
}
-func (dd *Destination) addNewPath(newPath *Path) {
+func (dd *Destination) AddNewPath(newPath *Path) {
dd.validatePath(newPath)
dd.newPathList = append(dd.newPathList, newPath)
}
diff --git a/table/destination_test.go b/table/destination_test.go
index 532cb5b1..2778b8a4 100644
--- a/table/destination_test.go
+++ b/table/destination_test.go
@@ -87,8 +87,8 @@ func TestCalculate(t *testing.T) {
path2.Filter("1", POLICY_DIRECTION_IMPORT)
d := NewDestination(nlri)
- d.addNewPath(path1)
- d.addNewPath(path2)
+ d.AddNewPath(path1)
+ d.AddNewPath(path2)
d.Calculate([]string{"1", "2"})
@@ -96,7 +96,7 @@ func TestCalculate(t *testing.T) {
assert.Equal(t, len(d.GetKnownPathList("2")), 1)
assert.Equal(t, len(d.knownPathList), 2)
- d.addWithdraw(path1.Clone(true))
+ d.AddWithdraw(path1.Clone(true))
d.Calculate([]string{"1", "2"})
@@ -121,7 +121,7 @@ func TestCalculate2(t *testing.T) {
path1 := ProcessMessage(update1, peer1, time.Now())[0]
d := NewDestination(nlri)
- d.addNewPath(path1)
+ d.AddNewPath(path1)
d.Calculate(nil)
// suppose peer2 sends grammaatically correct but semantically flawed update message
@@ -131,7 +131,7 @@ func TestCalculate2(t *testing.T) {
path2 := ProcessMessage(update2, peer2, time.Now())[0]
assert.Equal(t, path2.IsWithdraw, true)
- d.addWithdraw(path2)
+ d.AddWithdraw(path2)
d.Calculate(nil)
// we have a path from peer1 here
@@ -142,7 +142,7 @@ func TestCalculate2(t *testing.T) {
path3 := ProcessMessage(update3, peer2, time.Now())[0]
assert.Equal(t, path3.IsWithdraw, false)
- d.addNewPath(path3)
+ d.AddNewPath(path3)
d.Calculate(nil)
// this time, we have paths from peer1 and peer2
@@ -153,7 +153,7 @@ func TestCalculate2(t *testing.T) {
update4 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri})
path4 := ProcessMessage(update4, peer3, time.Now())[0]
- d.addNewPath(path4)
+ d.AddNewPath(path4)
d.Calculate(nil)
// we must have paths from peer1, peer2 and peer3
@@ -185,8 +185,8 @@ func TestImplicitWithdrawCalculate(t *testing.T) {
path2.Filter("3", POLICY_DIRECTION_IMPORT)
d := NewDestination(nlri)
- d.addNewPath(path1)
- d.addNewPath(path2)
+ d.AddNewPath(path1)
+ d.AddNewPath(path2)
d.Calculate(nil)
@@ -206,7 +206,7 @@ func TestImplicitWithdrawCalculate(t *testing.T) {
path3 := ProcessMessage(updateMsg, peer1, time.Now())[0]
path3.Filter("1", POLICY_DIRECTION_IMPORT)
- d.addNewPath(path3)
+ d.AddNewPath(path3)
d.Calculate(nil)
assert.Equal(t, len(d.GetKnownPathList("1")), 0) // peer "1" is the originator
@@ -289,8 +289,8 @@ func TestTimeTieBreaker(t *testing.T) {
path2 := ProcessMessage(updateMsg, peer2, time.Now().Add(-1*time.Hour))[0] // older than path1
d := NewDestination(nlri)
- d.addNewPath(path1)
- d.addNewPath(path2)
+ d.AddNewPath(path1)
+ d.AddNewPath(path2)
d.Calculate(nil)
@@ -300,8 +300,8 @@ func TestTimeTieBreaker(t *testing.T) {
// this option disables tie breaking by age
SelectionOptions.ExternalCompareRouterId = true
d = NewDestination(nlri)
- d.addNewPath(path1)
- d.addNewPath(path2)
+ d.AddNewPath(path1)
+ d.AddNewPath(path2)
d.Calculate(nil)
@@ -434,8 +434,8 @@ func TestMultipath(t *testing.T) {
path2 := ProcessMessage(updateMsg, peer2, time.Now())[0]
d := NewDestination(nlri[0])
- d.addNewPath(path1)
- d.addNewPath(path2)
+ d.AddNewPath(path1)
+ d.AddNewPath(path2)
best, w, multi := d.Calculate([]string{GLOBAL_RIB_NAME})
assert.Equal(t, len(best), 1)
@@ -444,7 +444,7 @@ func TestMultipath(t *testing.T) {
assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME)), 2)
path3 := path2.Clone(true)
- d.addWithdraw(path3)
+ d.AddWithdraw(path3)
best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME})
assert.Equal(t, len(best), 1)
assert.Equal(t, len(w), 1)
@@ -462,7 +462,7 @@ func TestMultipath(t *testing.T) {
}
updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
path4 := ProcessMessage(updateMsg, peer3, time.Now())[0]
- d.addNewPath(path4)
+ d.AddNewPath(path4)
best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME})
assert.Equal(t, len(best), 1)
@@ -479,7 +479,7 @@ func TestMultipath(t *testing.T) {
}
updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri)
path5 := ProcessMessage(updateMsg, peer2, time.Now())[0]
- d.addNewPath(path5)
+ d.AddNewPath(path5)
best, w, multi = d.Calculate([]string{GLOBAL_RIB_NAME})
assert.Equal(t, len(best), 1)
diff --git a/table/table.go b/table/table.go
index 33db8130..d5434005 100644
--- a/table/table.go
+++ b/table/table.go
@@ -44,10 +44,10 @@ func (t *Table) insert(path *Path) *Destination {
if path.IsWithdraw {
// withdraw insert
- dest.addWithdraw(path)
+ dest.AddWithdraw(path)
} else {
// path insert
- dest.addNewPath(path)
+ dest.AddNewPath(path)
}
return dest
}
@@ -58,7 +58,7 @@ func (t *Table) DeleteDestByPeer(peerInfo *PeerInfo) []*Destination {
match := false
for _, p := range dst.knownPathList {
if p.GetSource().Equal(peerInfo) {
- dst.addWithdraw(p)
+ dst.AddWithdraw(p)
match = true
}
}