diff options
author | Satoshi Fujimoto <satoshi.fujimoto7@gmail.com> | 2017-11-09 15:11:15 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-11-26 21:44:29 +0900 |
commit | b1953e81d6cadcd6e1ec28031d3f9f460d3d954d (patch) | |
tree | 6a0e1a5b510457c4870a9c9432a732eb0da3f4cb | |
parent | d20111fc1b2ef95de497a731ca692529f3e4fc99 (diff) |
cmd/neighbor: Refactor ShowRoute()
For readability and maintainability, separate ShowRoute()
into some small functions.
Signed-off-by: Satoshi Fujimoto <satoshi.fujimoto7@gmail.com>
-rw-r--r-- | gobgp/cmd/monitor.go | 53 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 296 | ||||
-rw-r--r-- | table/path.go | 30 |
3 files changed, 221 insertions, 158 deletions
diff --git a/gobgp/cmd/monitor.go b/gobgp/cmd/monitor.go index bc59e98f..d62f98cb 100644 --- a/gobgp/cmd/monitor.go +++ b/gobgp/cmd/monitor.go @@ -26,6 +26,56 @@ import ( "github.com/spf13/cobra" ) +func makeMonitorRouteArgs(p *table.Path, showIdentifier bgp.BGPAddPathMode) []interface{} { + pathStr := make([]interface{}, 0) + + // Title + title := "ROUTE" + if p.IsWithdraw { + title = "DELROUTE" + } + pathStr = append(pathStr, title) + + // NLRI + // If Add-Path required, append Path Identifier. + nlri := p.GetNlri() + if showIdentifier != bgp.BGP_ADD_PATH_NONE { + pathStr = append(pathStr, nlri.PathIdentifier()) + } + pathStr = append(pathStr, nlri) + + // Next Hop + nexthop := "fictitious" + if n := p.GetNexthop(); n != nil { + nexthop = p.GetNexthop().String() + } + pathStr = append(pathStr, nexthop) + + // AS_PATH + pathStr = append(pathStr, p.GetAsString()) + + // Path Attributes + pathStr = append(pathStr, getPathAttributeString(p)) + + return pathStr +} + +func monitorRoute(pathList []*table.Path, showIdentifier bgp.BGPAddPathMode) { + var pathStrs [][]interface{} + + for _, p := range pathList { + pathStrs = append(pathStrs, makeMonitorRouteArgs(p, showIdentifier)) + } + + format := "[%s] %s via %s aspath [%s] attrs %s\n" + if showIdentifier != bgp.BGP_ADD_PATH_NONE { + format = "[%s] %d:%s via %s aspath [%s] attrs %s\n" + } + for _, pathStr := range pathStrs { + fmt.Printf(format, pathStr...) + } +} + func NewMonitorCmd() *cobra.Command { var current bool @@ -44,8 +94,7 @@ func NewMonitorCmd() *cobra.Command { j, _ := json.Marshal(dst.GetAllKnownPathList()) fmt.Println(string(j)) } else { - ds := [][]*table.Path{dst.GetAllKnownPathList()} - ShowRoute(ds, false, false, false, true, false, showIdentifier) + monitorRoute(dst.GetAllKnownPathList(), showIdentifier) } } } diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 558e38e2..da538606 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -31,6 +31,29 @@ import ( "github.com/osrg/gobgp/table" ) +// used in showRoute() to determine the width of each column +var ( + columnWidthPrefix = 20 + columnWidthNextHop = 20 + columnWidthAsPath = 20 + columnWidthLabel = 10 +) + +func updateColumnWidth(nlri, nexthop, aspath, label string) { + if prefixLen := len(nlri); columnWidthPrefix < prefixLen { + columnWidthPrefix = prefixLen + } + if columnWidthNextHop < len(nexthop) { + columnWidthNextHop = len(nexthop) + } + if columnWidthAsPath < len(aspath) { + columnWidthAsPath = len(aspath) + } + if columnWidthLabel < len(label) { + columnWidthLabel = len(label) + } +} + func getNeighbors(vrf string) (neighbors, error) { if vrf != "" { n, err := client.ListNeighborByVRF(vrf) @@ -407,176 +430,137 @@ type AsPathFormat struct { separator string } -func showRoute(destinationList [][]*table.Path, showAge, showBest, showLabel, isMonitor, printHeader bool, showIdentifier bgp.BGPAddPathMode) { - - var pathStrs [][]interface{} - maxPrefixLen := 20 - maxNexthopLen := 20 - maxAsPathLen := 20 - maxLabelLen := 10 +func getPathSymbolString(p *table.Path, idx int, showBest bool) string { + symbols := "" + if p.IsStale() { + symbols += "S" + } + switch p.ValidationStatus() { + case config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND: + symbols += "N" + case config.RPKI_VALIDATION_RESULT_TYPE_VALID: + symbols += "V" + case config.RPKI_VALIDATION_RESULT_TYPE_INVALID: + symbols += "I" + } + if showBest { + if idx == 0 && !p.IsNexthopInvalid { + symbols += "*>" + } else { + symbols += "* " + } + } + return symbols +} - now := time.Now() - for _, pathList := range destinationList { - for idx, p := range pathList { - nexthop := "fictitious" - if n := p.GetNexthop(); n != nil { - nexthop = p.GetNexthop().String() +func getPathAttributeString(p *table.Path) string { + s := make([]string, 0) + for _, a := range p.GetPathAttrs() { + switch a.GetType() { + case bgp.BGP_ATTR_TYPE_NEXT_HOP, bgp.BGP_ATTR_TYPE_MP_REACH_NLRI, bgp.BGP_ATTR_TYPE_AS_PATH, bgp.BGP_ATTR_TYPE_AS4_PATH: + continue + default: + s = append(s, a.String()) + } + } + switch n := p.GetNlri().(type) { + case *bgp.EVPNNLRI: + // We print non route key fields like path attributes. + switch route := n.RouteTypeData.(type) { + case *bgp.EVPNMacIPAdvertisementRoute: + s = append(s, fmt.Sprintf("[ESI: %s]", route.ESI.String())) + case *bgp.EVPNIPPrefixRoute: + s = append(s, fmt.Sprintf("[ESI: %s]", route.ESI.String())) + if route.GWIPAddress != nil { + s = append(s, fmt.Sprintf("[GW: %s]", route.GWIPAddress.String())) } - aspathstr := p.GetAsString() + } + } + return fmt.Sprint(s) +} - nlri := p.GetNlri() - prefixLen := len(nlri.String()) - if maxPrefixLen < prefixLen { - maxPrefixLen = prefixLen - } +func makeShowRouteArgs(p *table.Path, idx int, now time.Time, showAge, showBest, showLabel bool, showIdentifier bgp.BGPAddPathMode) []interface{} { + nlri := p.GetNlri() - s := []string{} - for _, a := range p.GetPathAttrs() { - switch a.GetType() { - case bgp.BGP_ATTR_TYPE_NEXT_HOP, bgp.BGP_ATTR_TYPE_MP_REACH_NLRI, bgp.BGP_ATTR_TYPE_AS_PATH, bgp.BGP_ATTR_TYPE_AS4_PATH: - continue - default: - s = append(s, a.String()) - } - } - switch n := nlri.(type) { - case *bgp.EVPNNLRI: - // We print non route key fields like path attributes. - switch route := n.RouteTypeData.(type) { - case *bgp.EVPNMacIPAdvertisementRoute: - s = append(s, fmt.Sprintf("[ESI: %s]", route.ESI.String())) - case *bgp.EVPNIPPrefixRoute: - s = append(s, fmt.Sprintf("[ESI: %s]", route.ESI.String())) - if route.GWIPAddress != nil { - s = append(s, fmt.Sprintf("[GW: %s]", route.GWIPAddress.String())) - } - } - } - pattrstr := fmt.Sprint(s) + // Path Symbols (e.g. "*>") + args := []interface{}{getPathSymbolString(p, idx, showBest)} - if maxNexthopLen < len(nexthop) { - maxNexthopLen = len(nexthop) - } + // Path Identifier + switch showIdentifier { + case bgp.BGP_ADD_PATH_RECEIVE: + args = append(args, fmt.Sprint(nlri.PathIdentifier())) + case bgp.BGP_ADD_PATH_SEND: + args = append(args, fmt.Sprint(nlri.PathLocalIdentifier())) + } - if maxAsPathLen < len(aspathstr) { - maxAsPathLen = len(aspathstr) - } + // NLRI + args = append(args, nlri) - best := "" - if p.IsStale() { - best += "S" - } - switch p.ValidationStatus() { - case config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND: - best += "N" - case config.RPKI_VALIDATION_RESULT_TYPE_VALID: - best += "V" - case config.RPKI_VALIDATION_RESULT_TYPE_INVALID: - best += "I" - } - if showBest { - if idx == 0 && !p.IsNexthopInvalid { - best += "*>" - } else { - best += "* " - } - } + // Label + label := "" + if showLabel { + label = p.GetLabelString() + args = append(args, label) + } - if isMonitor { - title := "ROUTE" - if p.IsWithdraw { - title = "DELROUTE" - } - if showIdentifier != bgp.BGP_ADD_PATH_NONE { - pathStrs = append(pathStrs, []interface{}{title, nlri.PathIdentifier(), nlri, nexthop, aspathstr, pattrstr}) - } else { - pathStrs = append(pathStrs, []interface{}{title, nlri, nexthop, aspathstr, pattrstr}) - } - } else { - args := []interface{}{best} - switch showIdentifier { - case bgp.BGP_ADD_PATH_RECEIVE: - args = append(args, fmt.Sprint(nlri.PathIdentifier())) - case bgp.BGP_ADD_PATH_SEND: - args = append(args, fmt.Sprint(nlri.PathLocalIdentifier())) - } - args = append(args, nlri) - if showLabel { - label := "" - switch n := nlri.(type) { - case *bgp.LabeledIPAddrPrefix: - label = n.Labels.String() - case *bgp.LabeledIPv6AddrPrefix: - label = n.Labels.String() - case *bgp.LabeledVPNIPAddrPrefix: - label = n.Labels.String() - case *bgp.LabeledVPNIPv6AddrPrefix: - label = n.Labels.String() - case *bgp.EVPNNLRI: - switch route := n.RouteTypeData.(type) { - case *bgp.EVPNEthernetAutoDiscoveryRoute: - label = fmt.Sprintf("[%d]", route.Label) - case *bgp.EVPNMacIPAdvertisementRoute: - var l []string - for _, i := range route.Labels { - l = append(l, strconv.Itoa(int(i))) - } - label = fmt.Sprintf("[%s]", strings.Join(l, ",")) - case *bgp.EVPNIPPrefixRoute: - label = fmt.Sprintf("[%d]", route.Label) - } - } - if maxLabelLen < len(label) { - maxLabelLen = len(label) - } - args = append(args, label) - } - args = append(args, []interface{}{nexthop, aspathstr}...) - if showAge { - args = append(args, formatTimedelta(int64(now.Sub(p.GetTimestamp()).Seconds()))) - } - args = append(args, pattrstr) - pathStrs = append(pathStrs, args) - } - } + // Next Hop + nexthop := "fictitious" + if n := p.GetNexthop(); n != nil { + nexthop = p.GetNexthop().String() } + args = append(args, nexthop) - var format string - if isMonitor { - format = "[%s] %d:%s via %s aspath [%s] attrs %s\n" - } else { - format = fmt.Sprintf("%%-3s") - if showIdentifier != bgp.BGP_ADD_PATH_NONE { - format += "%-3s " - } - format += fmt.Sprintf("%%-%ds ", maxPrefixLen) - if showLabel { - format += fmt.Sprintf("%%-%ds ", maxLabelLen) - } - format += fmt.Sprintf("%%-%ds %%-%ds ", maxNexthopLen, maxAsPathLen) - if showAge { - format += "%-10s " - } - format += "%-s\n" + // AS_PATH + aspathstr := p.GetAsString() + args = append(args, aspathstr) + + // Age + if showAge { + args = append(args, formatTimedelta(int64(now.Sub(p.GetTimestamp()).Seconds()))) } - if printHeader { - args := []interface{}{""} - if showIdentifier != bgp.BGP_ADD_PATH_NONE { - args = append(args, "ID") - } - args = append(args, "Network") - if showLabel { - args = append(args, "Labels") - } - args = append(args, []interface{}{"Next Hop", "AS_PATH"}...) - if showAge { - args = append(args, "Age") + // Path Attributes + pattrstr := getPathAttributeString(p) + args = append(args, pattrstr) + + updateColumnWidth(nlri.String(), nexthop, aspathstr, label) + + return args +} + +func showRoute(destinationList [][]*table.Path, showAge, showBest, showLabel bool, showIdentifier bgp.BGPAddPathMode) { + var pathStrs [][]interface{} + now := time.Now() + for _, pathList := range destinationList { + for idx, p := range pathList { + pathStrs = append(pathStrs, makeShowRouteArgs(p, idx, now, showAge, showBest, showLabel, showIdentifier)) } - args = append(args, "Attrs") - fmt.Printf(format, args...) } + headers := make([]interface{}, 0) + var format string + headers = append(headers, "") // Symbols + format = fmt.Sprintf("%%-3s") + if showIdentifier != bgp.BGP_ADD_PATH_NONE { + headers = append(headers, "ID") + format += "%-3s " + } + headers = append(headers, "Network") + format += fmt.Sprintf("%%-%ds ", columnWidthPrefix) + if showLabel { + headers = append(headers, "Labels") + format += fmt.Sprintf("%%-%ds ", columnWidthLabel) + } + headers = append(headers, "Next Hop", "AS_PATH") + format += fmt.Sprintf("%%-%ds %%-%ds ", columnWidthNextHop, columnWidthAsPath) + if showAge { + headers = append(headers, "Age") + format += "%-10s " + } + headers = append(headers, "Attrs") + format += "%-s\n" + + fmt.Printf(format, headers...) for _, pathStr := range pathStrs { fmt.Printf(format, pathStr...) } @@ -842,7 +826,7 @@ func showNeighborRib(r string, name string, args []string) error { ds = append(ds, ps) } if len(ds) > 0 { - showRoute(ds, showAge, showBest, showLabel, false, true, showIdentifier) + showRoute(ds, showAge, showBest, showLabel, showIdentifier) } else { fmt.Println("Network not in table") } diff --git a/table/path.go b/table/path.go index 9f041786..6c97dea2 100644 --- a/table/path.go +++ b/table/path.go @@ -22,6 +22,8 @@ import ( "math" "net" "sort" + "strconv" + "strings" "time" log "github.com/sirupsen/logrus" @@ -690,6 +692,34 @@ func (path *Path) getAsListofSpecificType(getAsSeq, getAsSet bool) []uint32 { return asList } +func (path *Path) GetLabelString() string { + label := "" + switch n := path.GetNlri().(type) { + case *bgp.LabeledIPAddrPrefix: + label = n.Labels.String() + case *bgp.LabeledIPv6AddrPrefix: + label = n.Labels.String() + case *bgp.LabeledVPNIPAddrPrefix: + label = n.Labels.String() + case *bgp.LabeledVPNIPv6AddrPrefix: + label = n.Labels.String() + case *bgp.EVPNNLRI: + switch route := n.RouteTypeData.(type) { + case *bgp.EVPNEthernetAutoDiscoveryRoute: + label = fmt.Sprintf("[%d]", route.Label) + case *bgp.EVPNMacIPAdvertisementRoute: + var l []string + for _, i := range route.Labels { + l = append(l, strconv.Itoa(int(i))) + } + label = fmt.Sprintf("[%s]", strings.Join(l, ",")) + case *bgp.EVPNIPPrefixRoute: + label = fmt.Sprintf("[%d]", route.Label) + } + } + return label +} + // PrependAsn prepends AS number. // This function updates the AS_PATH attribute as follows. // (If the peer is in the confederation member AS, |