diff options
-rw-r--r-- | gobgp/monitor.go | 2 | ||||
-rw-r--r-- | gobgp/neighbor.go | 29 | ||||
-rw-r--r-- | server/server.go | 29 | ||||
-rw-r--r-- | table/destination.go | 16 |
4 files changed, 64 insertions, 12 deletions
diff --git a/gobgp/monitor.go b/gobgp/monitor.go index a093ac31..bd96622d 100644 --- a/gobgp/monitor.go +++ b/gobgp/monitor.go @@ -63,7 +63,7 @@ func NewMonitorCmd() *cobra.Command { j, _ := json.Marshal(p) fmt.Println(string(j)) } else { - showRoute([]*Path{p}, false, false, true) + showRoute([]*Path{p}, false, false, true, true) } } diff --git a/gobgp/neighbor.go b/gobgp/neighbor.go index adc2b9fb..b8c60273 100644 --- a/gobgp/neighbor.go +++ b/gobgp/neighbor.go @@ -231,7 +231,7 @@ type AsPathFormat struct { separator string } -func showRoute(pathList []*Path, showAge bool, showBest bool, isMonitor bool) { +func showRoute(pathList []*Path, showAge bool, showBest bool, isMonitor, printHeader bool) { var pathStrs [][]interface{} maxPrefixLen := 20 @@ -349,10 +349,14 @@ func showRoute(pathList []*Path, showAge bool, showBest bool, isMonitor bool) { format = "[%s] %s via %s aspath [%s] attrs %s\n" } else if showAge { format = fmt.Sprintf("%%-3s %%-%ds %%-%ds %%-%ds %%-10s %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen) - fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Age", "Attrs") + if printHeader { + fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Age", "Attrs") + } } else { format = fmt.Sprintf("%%-3s %%-%ds %%-%ds %%-%ds %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen) - fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Attrs") + if printHeader { + fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Attrs") + } } for _, pathStr := range pathStrs { @@ -414,6 +418,7 @@ func showNeighborRib(r string, name string, args []string) error { dsts := []*Destination{} maxOnes := 0 + counter := 0 for { d, e := stream.Recv() if e == io.EOF { @@ -443,6 +448,17 @@ func showNeighborRib(r string, name string, args []string) error { if err != nil { return err } + if rf == bgp.RF_IPv4_UC && !globalOpts.Json && len(dst.Paths) > 0 { + ps := paths{} + ps = append(ps, dst.Paths...) + sort.Sort(ps) + if counter == 0 { + showRoute(ps, showAge, showBest, false, true) + } else { + showRoute(ps, showAge, showBest, false, false) + } + counter++ + } dsts = append(dsts, dst) } @@ -452,6 +468,11 @@ func showNeighborRib(r string, name string, args []string) error { return nil } + if rf == bgp.RF_IPv4_UC && counter != 0 { + // we already showed + return nil + } + ps := paths{} for _, dst := range dsts { ps = append(ps, dst.Paths...) @@ -463,7 +484,7 @@ func showNeighborRib(r string, name string, args []string) error { } sort.Sort(ps) - showRoute(ps, showAge, showBest, false) + showRoute(ps, showAge, showBest, false, true) return nil } diff --git a/server/server.go b/server/server.go index 063431d6..78e9095f 100644 --- a/server/server.go +++ b/server/server.go @@ -19,6 +19,7 @@ import ( "bytes" "fmt" log "github.com/Sirupsen/logrus" + "github.com/armon/go-radix" "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet" @@ -1089,12 +1090,28 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { case REQ_GLOBAL_RIB: if t, ok := server.localRibMap[GLOBAL_RIB_NAME].rib.Tables[grpcReq.RouteFamily]; ok { results := make([]*GrpcResponse, len(t.GetDestinations())) - i := 0 - for _, dst := range t.GetDestinations() { - result := &GrpcResponse{} - result.Data = dst.ToApiStruct() - results[i] = result - i++ + if grpcReq.RouteFamily == bgp.RF_IPv4_UC { + r := radix.New() + for _, dst := range t.GetDestinations() { + result := &GrpcResponse{} + result.Data = dst.ToApiStruct() + r.Insert(dst.RadixKey, result) + } + i := 0 + r.Walk(func(s string, v interface{}) bool { + r, _ := v.(*GrpcResponse) + results[i] = r + i++ + return false + }) + } else { + i := 0 + for _, dst := range t.GetDestinations() { + result := &GrpcResponse{} + result.Data = dst.ToApiStruct() + results[i] = result + i++ + } } go sendMultipleResponses(grpcReq, results) } diff --git a/table/destination.go b/table/destination.go index 75072732..f669cced 100644 --- a/table/destination.go +++ b/table/destination.go @@ -16,6 +16,7 @@ package table import ( + "bytes" "encoding/binary" "encoding/json" "fmt" @@ -71,16 +72,29 @@ type Destination struct { newPathList []*Path bestPath *Path bestPathReason string + RadixKey string } func NewDestination(nlri bgp.AddrPrefixInterface) *Destination { - return &Destination{ + d := &Destination{ routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()), nlri: nlri, knownPathList: make([]*Path, 0), withdrawList: make([]*Path, 0), newPathList: make([]*Path, 0), } + if d.routeFamily == bgp.RF_IPv4_UC { + d.RadixKey = func(cidr string) string { + _, n, _ := net.ParseCIDR(cidr) + ones, _ := n.Mask.Size() + var buffer bytes.Buffer + for i := 0; i < len(n.IP) && i < ones; i++ { + buffer.WriteString(fmt.Sprintf("%08b", n.IP[i])) + } + return buffer.String()[:ones] + }(nlri.String()) + } + return d } func (dd *Destination) MarshalJSON() ([]byte, error) { |