gobgp: support mrt injecting only best paths

$ gobgp mrt inject global --only-best your-mrt-dump-file

Signed-off-by: FUJITA Tomonori <[email protected]>
This commit is contained in:
FUJITA Tomonori
2016-07-31 16:31:50 +09:00
parent 848dcec1f7
commit 55f473d7fe
5 changed files with 85 additions and 44 deletions
+1
View File
@@ -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 {
+60 -20
View File
@@ -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 rf == bgp.RF_IPv4_UC {
path.Nlri, _ = nlri.Serialize()
}
for _, p := range e.PathAttributes {
b, err := p.Serialize()
if err != nil {
continue
if !onlyBest {
path := &api.Path{
Pattrs: make([][]byte, 0),
NoImplicitWithdraw: true,
SourceAsn: peers[e.PeerIndex].AS,
SourceId: peers[e.PeerIndex].BgpId.String(),
}
path.Pattrs = append(path.Pattrs, b)
}
paths = append(paths, path)
if rf == bgp.RF_IPv4_UC {
path.Nlri, _ = nlri.Serialize()
}
for _, p := range e.PathAttributes {
b, err := p.Serialize()
if err != nil {
continue
}
path.Pattrs = append(path.Pattrs, b)
}
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
}
+2 -2
View File
@@ -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)
}
+19 -19
View File
@@ -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)
+3 -3
View File
@@ -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
}
}