diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-07-31 16:31:50 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-07-31 16:31:50 +0900 |
commit | 55f473d7fe07a72dbddcc424d4d6bce76e609e1b (patch) | |
tree | 51c2072eeeb201037515bebca4b469a7bc9b13ce | |
parent | 848dcec1f7bfc8313c1bc88bbd11be4167fe624a (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.go | 1 | ||||
-rw-r--r-- | gobgp/cmd/mrt.go | 76 | ||||
-rw-r--r-- | table/destination.go | 4 | ||||
-rw-r--r-- | table/destination_test.go | 38 | ||||
-rw-r--r-- | table/table.go | 6 |
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 } } |