mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
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:
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user