diff options
-rw-r--r-- | api/util.go | 140 | ||||
-rw-r--r-- | client/client.go | 61 | ||||
-rw-r--r-- | gobgp/cmd/common.go | 12 | ||||
-rw-r--r-- | gobgp/cmd/monitor.go | 34 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 195 | ||||
-rw-r--r-- | gobgp/cmd/rpki.go | 5 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 66 | ||||
-rw-r--r-- | server/server.go | 2 | ||||
-rw-r--r-- | table/path.go | 62 | ||||
-rw-r--r-- | table/table.go | 22 |
10 files changed, 274 insertions, 325 deletions
diff --git a/api/util.go b/api/util.go index 90aa5384..721909c5 100644 --- a/api/util.go +++ b/api/util.go @@ -16,35 +16,13 @@ package gobgpapi import ( - "fmt" + "encoding/json" "net" - "time" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" - "github.com/osrg/gobgp/table" ) -type ToNativeOption struct { - LocalAS uint32 - LocalID net.IP - RouteReflectorClient bool - RouteReflectorClusterID net.IP - NLRI bgp.AddrPrefixInterface -} - -func (t *Table) ToNativeTable(option ...ToNativeOption) (*table.Table, error) { - dsts := make([]*table.Destination, 0, len(t.Destinations)) - for _, d := range t.Destinations { - dst, err := d.ToNativeDestination(option...) - if err != nil { - return nil, err - } - dsts = append(dsts, dst) - } - return table.NewTable(bgp.RouteFamily(t.Family), dsts...), nil -} - func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error) { afi, safi := bgp.RouteFamilyToAfiSafi(family) nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi) @@ -57,32 +35,32 @@ func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error return nlri, nil } -func (d *Destination) ToNativeDestination(option ...ToNativeOption) (*table.Destination, error) { - if len(d.Paths) == 0 { - return nil, fmt.Errorf("no path in destination") - } - nlri, err := d.Paths[0].GetNativeNlri() - if err != nil { - return nil, err - } - option = append(option, ToNativeOption{ - NLRI: nlri, +func (d *Destination) MarshalJSON() ([]byte, error) { + return json.Marshal(d.Paths) +} + +func (p *Path) MarshalJSON() ([]byte, error) { + nlri, _ := p.GetNativeNlri() + attrs, _ := p.GetNativePathAttributes() + return json.Marshal(struct { + Nlri bgp.AddrPrefixInterface `json:"nlri"` + Age int64 `json:"age"` + Best bool `json:"best"` + Attrs []bgp.PathAttributeInterface `json:"attrs"` + Stale bool `json:"stale"` + Withdrawal bool `json:"withdrawal,omitempty"` + SourceID net.IP `json:"source-id,omitempty"` + NeighborIP net.IP `json:"neighbor-ip,omitempty"` + }{ + Nlri: nlri, + Age: p.Age, + Best: p.Best, + Attrs: attrs, + Stale: p.Stale, + Withdrawal: p.IsWithdraw, + SourceID: net.ParseIP(p.SourceId), + NeighborIP: net.ParseIP(p.NeighborIp), }) - paths := make([]*table.Path, 0, len(d.Paths)) - for _, p := range d.Paths { - var path *table.Path - var err error - if p.Identifier > 0 { - path, err = p.ToNativePath() - } else { - path, err = p.ToNativePath(option...) - } - if err != nil { - return nil, err - } - paths = append(paths, path) - } - return table.NewDestination(nlri, 0, paths...), nil } func (p *Path) GetNativeNlri() (bgp.AddrPrefixInterface, error) { @@ -112,72 +90,6 @@ func (p *Path) GetNativePathAttributes() ([]bgp.PathAttributeInterface, error) { return UnmarshalPathAttributes(p.AnyPattrs) } -func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) { - info := &table.PeerInfo{ - AS: p.SourceAsn, - ID: net.ParseIP(p.SourceId), - Address: net.ParseIP(p.NeighborIp), - } - var nlri bgp.AddrPrefixInterface - for _, o := range option { - info.LocalAS = o.LocalAS - info.LocalID = o.LocalID - info.RouteReflectorClient = o.RouteReflectorClient - info.RouteReflectorClusterID = o.RouteReflectorClusterID - nlri = o.NLRI - } - if nlri == nil { - var err error - nlri, err = p.GetNativeNlri() - if err != nil { - return nil, err - } - } - pattr, err := p.GetNativePathAttributes() - if err != nil { - return nil, err - } - t := time.Unix(p.Age, 0) - nlri.SetPathIdentifier(p.Identifier) - nlri.SetPathLocalIdentifier(p.LocalIdentifier) - path := table.NewPath(info, nlri, p.IsWithdraw, pattr, t, false) - - // p.ValidationDetail.* are already validated - matched, _ := NewROAListFromApiStructList(p.ValidationDetail.Matched) - unmatchedAs, _ := NewROAListFromApiStructList(p.ValidationDetail.UnmatchedAs) - unmatchedLength, _ := NewROAListFromApiStructList(p.ValidationDetail.UnmatchedLength) - - path.SetValidation(&table.Validation{ - Status: config.IntToRpkiValidationResultTypeMap[int(p.Validation)], - Reason: table.IntToRpkiValidationReasonTypeMap[int(p.ValidationDetail.Reason)], - Matched: matched, - UnmatchedAs: unmatchedAs, - UnmatchedLength: unmatchedLength, - }) - path.MarkStale(p.Stale) - path.IsNexthopInvalid = p.IsNexthopInvalid - return path, nil -} - -func NewROAListFromApiStructList(l []*Roa) ([]*table.ROA, error) { - roas := make([]*table.ROA, 0, len(l)) - for _, r := range l { - ip := net.ParseIP(r.Prefix) - family := bgp.RF_IPv4_UC - if ip == nil { - return nil, fmt.Errorf("invalid prefix %s", r.Prefix) - } else { - if ip.To4() == nil { - family = bgp.RF_IPv6_UC - } - } - afi, _ := bgp.RouteFamilyToAfiSafi(family) - roa := table.NewROA(int(afi), []byte(ip), uint8(r.Prefixlen), uint8(r.Maxlen), r.As, net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort)) - roas = append(roas, roa) - } - return roas, nil -} - func extractFamilyFromConfigAfiSafi(c *config.AfiSafi) uint32 { if c == nil { return 0 diff --git a/client/client.go b/client/client.go index 05877198..c733e592 100644 --- a/client/client.go +++ b/client/client.go @@ -244,24 +244,17 @@ func (cli *Client) SoftReset(addr string, family bgp.RouteFamily) error { return cli.softreset(addr, family, api.SoftResetNeighborRequest_BOTH) } -func (cli *Client) getRIB(resource api.Resource, name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) { - prefixList := make([]*api.TableLookupPrefix, 0, len(prefixes)) - for _, p := range prefixes { - prefixList = append(prefixList, &api.TableLookupPrefix{ - Prefix: p.Prefix, - LookupOption: api.TableLookupOption(p.LookupOption), - }) - } +func (cli *Client) getRIB(resource api.Resource, name string, family bgp.RouteFamily, prefixes []*api.TableLookupPrefix) (*api.Table, error) { stream, err := cli.cli.GetPath(context.Background(), &api.GetPathRequest{ Type: resource, Family: uint32(family), Name: name, - Prefixes: prefixList, + Prefixes: prefixes, }) if err != nil { return nil, err } - pathMap := make(map[string][]*table.Path) + pathMap := make(map[string][]*api.Path) for { p, err := stream.Recv() if err != nil { @@ -274,44 +267,40 @@ func (cli *Client) getRIB(resource api.Resource, name string, family bgp.RouteFa if err != nil { return nil, err } - var path *table.Path - if p.Identifier > 0 { - path, err = p.ToNativePath() - } else { - path, err = p.ToNativePath(api.ToNativeOption{ - NLRI: nlri, - }) - } - if err != nil { - return nil, err - } nlriStr := nlri.String() - pathMap[nlriStr] = append(pathMap[nlriStr], path) + pathMap[nlriStr] = append(pathMap[nlriStr], p) } - dstList := make([]*table.Destination, 0, len(pathMap)) + dstList := make([]*api.Destination, 0, len(pathMap)) for _, pathList := range pathMap { - dstList = append(dstList, table.NewDestination(pathList[0].GetNlri(), 0, pathList...)) + nlri, _ := pathList[0].GetNativeNlri() + dstList = append(dstList, &api.Destination{ + Prefix: nlri.String(), + Paths: pathList, + }) } - return table.NewTable(family, dstList...), nil + return &api.Table{ + Family: uint32(family), + Destinations: dstList, + }, nil } -func (cli *Client) GetRIB(family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) { +func (cli *Client) GetRIB(family bgp.RouteFamily, prefixes []*api.TableLookupPrefix) (*api.Table, error) { return cli.getRIB(api.Resource_GLOBAL, "", family, prefixes) } -func (cli *Client) GetLocalRIB(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) { +func (cli *Client) GetLocalRIB(name string, family bgp.RouteFamily, prefixes []*api.TableLookupPrefix) (*api.Table, error) { return cli.getRIB(api.Resource_LOCAL, name, family, prefixes) } -func (cli *Client) GetAdjRIBIn(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) { +func (cli *Client) GetAdjRIBIn(name string, family bgp.RouteFamily, prefixes []*api.TableLookupPrefix) (*api.Table, error) { return cli.getRIB(api.Resource_ADJ_IN, name, family, prefixes) } -func (cli *Client) GetAdjRIBOut(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) { +func (cli *Client) GetAdjRIBOut(name string, family bgp.RouteFamily, prefixes []*api.TableLookupPrefix) (*api.Table, error) { return cli.getRIB(api.Resource_ADJ_OUT, name, family, prefixes) } -func (cli *Client) GetVRFRIB(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) { +func (cli *Client) GetVRFRIB(name string, family bgp.RouteFamily, prefixes []*api.TableLookupPrefix) (*api.Table, error) { return cli.getRIB(api.Resource_VRF, name, family, prefixes) } @@ -788,14 +777,14 @@ func (cli *Client) GetRPKI() ([]*config.RpkiServer, error) { return servers, nil } -func (cli *Client) GetROA(family bgp.RouteFamily) ([]*table.ROA, error) { +func (cli *Client) GetROA(family bgp.RouteFamily) ([]*api.Roa, error) { rsp, err := cli.cli.GetRoa(context.Background(), &api.GetRoaRequest{ Family: uint32(family), }) if err != nil { return nil, err } - return api.NewROAListFromApiStructList(rsp.Roas) + return rsp.Roas, nil } func (cli *Client) AddRPKIServer(address string, port, lifetime int) error { @@ -874,12 +863,8 @@ type MonitorRIBClient struct { stream api.GobgpApi_MonitorRibClient } -func (c *MonitorRIBClient) Recv() (*table.Destination, error) { - d, err := c.stream.Recv() - if err != nil { - return nil, err - } - return d.ToNativeDestination() +func (c *MonitorRIBClient) Recv() (*api.Destination, error) { + return c.stream.Recv() } func (cli *Client) MonitorRIB(family bgp.RouteFamily, current bool) (*MonitorRIBClient, error) { diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go index 7add79a1..94b5d8ad 100644 --- a/gobgp/cmd/common.go +++ b/gobgp/cmd/common.go @@ -333,3 +333,15 @@ func exitWithError(err error) { printError(err) os.Exit(1) } + +func getNextHopFromPathAttributes(attrs []bgp.PathAttributeInterface) net.IP { + for _, attr := range attrs { + switch a := attr.(type) { + case *bgp.PathAttributeNextHop: + return a.Value + case *bgp.PathAttributeMpReachNLRI: + return a.Nexthop + } + } + return nil +} diff --git a/gobgp/cmd/monitor.go b/gobgp/cmd/monitor.go index b99575ae..af91faf3 100644 --- a/gobgp/cmd/monitor.go +++ b/gobgp/cmd/monitor.go @@ -23,11 +23,11 @@ import ( "github.com/spf13/cobra" + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/packet/bgp" - "github.com/osrg/gobgp/table" ) -func makeMonitorRouteArgs(p *table.Path, showIdentifier bgp.BGPAddPathMode) []interface{} { +func makeMonitorRouteArgs(p *api.Path, showIdentifier bgp.BGPAddPathMode) []interface{} { pathStr := make([]interface{}, 0) // Title @@ -39,29 +39,39 @@ func makeMonitorRouteArgs(p *table.Path, showIdentifier bgp.BGPAddPathMode) []in // NLRI // If Add-Path required, append Path Identifier. - nlri := p.GetNlri() + nlri, _ := p.GetNativeNlri() if showIdentifier != bgp.BGP_ADD_PATH_NONE { - pathStr = append(pathStr, nlri.PathIdentifier()) + pathStr = append(pathStr, p.GetIdentifier()) } pathStr = append(pathStr, nlri) + attrs, _ := p.GetNativePathAttributes() // Next Hop nexthop := "fictitious" - if n := p.GetNexthop(); n != nil { - nexthop = p.GetNexthop().String() + if n := getNextHopFromPathAttributes(attrs); n != nil { + nexthop = n.String() } pathStr = append(pathStr, nexthop) // AS_PATH - pathStr = append(pathStr, p.GetAsString()) + aspathstr := func() string { + for _, attr := range attrs { + switch a := attr.(type) { + case *bgp.PathAttributeAsPath: + return bgp.AsPathString(a) + } + } + return "" + }() + pathStr = append(pathStr, aspathstr) // Path Attributes - pathStr = append(pathStr, getPathAttributeString(p)) + pathStr = append(pathStr, getPathAttributeString(nlri, attrs)) return pathStr } -func monitorRoute(pathList []*table.Path, showIdentifier bgp.BGPAddPathMode) { +func monitorRoute(pathList []*api.Path, showIdentifier bgp.BGPAddPathMode) { var pathStrs [][]interface{} for _, p := range pathList { @@ -82,7 +92,7 @@ func NewMonitorCmd() *cobra.Command { var current bool monitor := func(recver interface { - Recv() (*table.Destination, error) + Recv() (*api.Destination, error) }, showIdentifier bgp.BGPAddPathMode) { for { dst, err := recver.Recv() @@ -92,10 +102,10 @@ func NewMonitorCmd() *cobra.Command { exitWithError(err) } if globalOpts.Json { - j, _ := json.Marshal(dst.GetAllKnownPathList()) + j, _ := json.Marshal(dst.Paths) fmt.Println(string(j)) } else { - monitorRoute(dst.GetAllKnownPathList(), showIdentifier) + monitorRoute(dst.Paths, showIdentifier) } } } diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 2e30fc8f..25a3084b 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -16,6 +16,7 @@ package cmd import ( + "bytes" "encoding/json" "fmt" "net" @@ -29,6 +30,8 @@ import ( "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" + + api "github.com/osrg/gobgp/api" ) // used in showRoute() to determine the width of each column @@ -424,18 +427,21 @@ func showNeighbor(args []string) error { type AsPathFormat struct{} -func getPathSymbolString(p *table.Path, idx int, showBest bool) string { +func getPathSymbolString(p *api.Path, idx int, showBest bool) string { symbols := "" - if p.IsStale() { + if p.Stale { 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 v := p.GetValidationDetail(); v != nil { + switch v.State { + case api.RPKIValidation_STATE_NOT_FOUND: + symbols += "N" + case api.RPKIValidation_STATE_VALID: + symbols += "V" + case api.RPKIValidation_STATE_INVALID: + symbols += "I" + } + } if showBest { if idx == 0 && !p.IsNexthopInvalid { @@ -447,9 +453,9 @@ func getPathSymbolString(p *table.Path, idx int, showBest bool) string { return symbols } -func getPathAttributeString(p *table.Path) string { +func getPathAttributeString(nlri bgp.AddrPrefixInterface, attrs []bgp.PathAttributeInterface) string { s := make([]string, 0) - for _, a := range p.GetPathAttrs() { + for _, a := range attrs { 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 @@ -457,7 +463,7 @@ func getPathAttributeString(p *table.Path) string { s = append(s, a.String()) } } - switch n := p.GetNlri().(type) { + switch n := nlri.(type) { case *bgp.EVPNNLRI: // We print non route key fields like path attributes. switch route := n.RouteTypeData.(type) { @@ -473,8 +479,8 @@ func getPathAttributeString(p *table.Path) string { return fmt.Sprint(s) } -func makeShowRouteArgs(p *table.Path, idx int, now time.Time, showAge, showBest, showLabel bool, showIdentifier bgp.BGPAddPathMode) []interface{} { - nlri := p.GetNlri() +func makeShowRouteArgs(p *api.Path, idx int, now time.Time, showAge, showBest, showLabel bool, showIdentifier bgp.BGPAddPathMode) []interface{} { + nlri, _ := p.GetNativeNlri() // Path Symbols (e.g. "*>") args := []interface{}{getPathSymbolString(p, idx, showBest)} @@ -482,9 +488,9 @@ func makeShowRouteArgs(p *table.Path, idx int, now time.Time, showAge, showBest, // Path Identifier switch showIdentifier { case bgp.BGP_ADD_PATH_RECEIVE: - args = append(args, fmt.Sprint(nlri.PathIdentifier())) + args = append(args, fmt.Sprint(p.GetIdentifier())) case bgp.BGP_ADD_PATH_SEND: - args = append(args, fmt.Sprint(nlri.PathLocalIdentifier())) + args = append(args, fmt.Sprint(p.GetLocalIdentifier())) } // NLRI @@ -493,28 +499,38 @@ func makeShowRouteArgs(p *table.Path, idx int, now time.Time, showAge, showBest, // Label label := "" if showLabel { - label = p.GetLabelString() + label = bgp.LabelString(nlri) args = append(args, label) } + attrs, _ := p.GetNativePathAttributes() // Next Hop nexthop := "fictitious" - if n := p.GetNexthop(); n != nil { - nexthop = p.GetNexthop().String() + if n := getNextHopFromPathAttributes(attrs); n != nil { + nexthop = n.String() } args = append(args, nexthop) // AS_PATH - aspathstr := p.GetAsString() + aspathstr := func() string { + for _, attr := range attrs { + switch a := attr.(type) { + case *bgp.PathAttributeAsPath: + return bgp.AsPathString(a) + } + } + return "" + }() args = append(args, aspathstr) // Age if showAge { - args = append(args, formatTimedelta(int64(now.Sub(p.GetTimestamp()).Seconds()))) + t := time.Unix(p.Age, 0) + args = append(args, formatTimedelta(int64(now.Sub(t).Seconds()))) } // Path Attributes - pattrstr := getPathAttributeString(p) + pattrstr := getPathAttributeString(nlri, attrs) args = append(args, pattrstr) updateColumnWidth(nlri.String(), nexthop, aspathstr, label) @@ -522,11 +538,11 @@ func makeShowRouteArgs(p *table.Path, idx int, now time.Time, showAge, showBest, return args } -func showRoute(destinationList [][]*table.Path, showAge, showBest, showLabel bool, showIdentifier bgp.BGPAddPathMode) { - var pathStrs [][]interface{} +func showRoute(dsts []*api.Destination, showAge, showBest, showLabel bool, showIdentifier bgp.BGPAddPathMode) { + pathStrs := make([][]interface{}, 0, len(dsts)) now := time.Now() - for _, pathList := range destinationList { - for idx, p := range pathList { + for _, dst := range dsts { + for idx, p := range dst.Paths { pathStrs = append(pathStrs, makeShowRouteArgs(p, idx, now, showAge, showBest, showLabel, showIdentifier)) } } @@ -560,8 +576,7 @@ func showRoute(destinationList [][]*table.Path, showAge, showBest, showLabel boo } } -func checkOriginAsWasNotShown(p *table.Path, shownAs map[uint32]struct{}) bool { - asPath := p.GetAsPath().Value +func checkOriginAsWasNotShown(p *api.Path, asPath []bgp.AsPathParamInterface, shownAs map[uint32]struct{}) bool { // the path was generated in internal if len(asPath) == 0 { return false @@ -576,59 +591,67 @@ func checkOriginAsWasNotShown(p *table.Path, shownAs map[uint32]struct{}) bool { return true } -func showValidationInfo(p *table.Path, shownAs map[uint32]struct{}) error { - asPath := p.GetAsPath().Value +func showValidationInfo(p *api.Path, shownAs map[uint32]struct{}) error { + var asPath []bgp.AsPathParamInterface + attrs, _ := p.GetNativePathAttributes() + for _, attr := range attrs { + if attr.GetType() == bgp.BGP_ATTR_TYPE_AS_PATH { + asPath = attr.(*bgp.PathAttributeAsPath).Value + } + } + + nlri, _ := p.GetNativeNlri() if len(asPath) == 0 { - return fmt.Errorf("The path to %s was locally generated.\n", p.GetNlri().String()) - } else if !checkOriginAsWasNotShown(p, shownAs) { + return fmt.Errorf("The path to %s was locally generated.\n", nlri.String()) + } else if !checkOriginAsWasNotShown(p, asPath, shownAs) { return nil } - status := p.Validation().Status - reason := p.Validation().Reason + status := p.GetValidationDetail().State + reason := p.GetValidationDetail().Reason asList := asPath[len(asPath)-1].GetAS() origin := asList[len(asList)-1] - fmt.Printf("Target Prefix: %s, AS: %d\n", p.GetNlri().String(), origin) + fmt.Printf("Target Prefix: %s, AS: %d\n", nlri.String(), origin) fmt.Printf(" This route is %s", status) switch status { - case config.RPKI_VALIDATION_RESULT_TYPE_INVALID: + case api.RPKIValidation_STATE_INVALID: fmt.Printf(" reason: %s\n", reason) switch reason { - case table.RPKI_VALIDATION_REASON_TYPE_AS: + case api.RPKIValidation_REASON_AS: fmt.Println(" No VRP ASN matches the route origin ASN.") - case table.RPKI_VALIDATION_REASON_TYPE_LENGTH: + case api.RPKIValidation_REASON_LENGTH: fmt.Println(" Route Prefix length is greater than the maximum length allowed by VRP(s) matching this route origin ASN.") } - case config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND: + case api.RPKIValidation_STATE_NOT_FOUND: fmt.Println("\n No VRP Covers the Route Prefix") default: fmt.Print("\n\n") } - printVRPs := func(l []*table.ROA) { + printVRPs := func(l []*api.Roa) { if len(l) == 0 { fmt.Println(" No Entry") } else { var format string - if ip, _, _ := net.ParseCIDR(p.GetNlri().String()); ip.To4() != nil { + if ip, _, _ := net.ParseCIDR(nlri.String()); ip.To4() != nil { format = " %-18s %-6s %-10s\n" } else { format = " %-42s %-6s %-10s\n" } fmt.Printf(format, "Network", "AS", "MaxLen") for _, m := range l { - fmt.Printf(format, m.Prefix, fmt.Sprint(m.AS), fmt.Sprint(m.MaxLen)) + fmt.Printf(format, m.Prefix, fmt.Sprint(m.As), fmt.Sprint(m.Maxlen)) } } } fmt.Println(" Matched VRPs: ") - printVRPs(p.Validation().Matched) + printVRPs(p.GetValidationDetail().Matched) fmt.Println(" Unmatched AS VRPs: ") - printVRPs(p.Validation().UnmatchedAs) + printVRPs(p.GetValidationDetail().UnmatchedAs) fmt.Println(" Unmatched Length VRPs: ") - printVRPs(p.Validation().UnmatchedLength) + printVRPs(p.GetValidationDetail().UnmatchedLength) return nil } @@ -669,7 +692,6 @@ func showRibInfo(r, name string) error { fmt.Printf("Table %s\n", family) fmt.Printf("Destination: %d, Path: %d\n", info.NumDestination, info.NumPath) return nil - } func parseCIDRorIP(str string) (net.IP, *net.IPNet, error) { @@ -713,7 +735,7 @@ func showNeighborRib(r string, name string, args []string) error { showLabel = true } - var filter []*table.LookupPrefix + var filter []*api.TableLookupPrefix if len(args) > 0 { target := args[0] switch family { @@ -724,13 +746,13 @@ func showNeighborRib(r string, name string, args []string) error { return err } } - var option table.LookupOption + var option api.TableLookupOption args = args[1:] for len(args) != 0 { if args[0] == "longer-prefixes" { - option = table.LOOKUP_LONGER + option = api.TableLookupOption_LOOKUP_LONGER } else if args[0] == "shorter-prefixes" { - option = table.LOOKUP_SHORTER + option = api.TableLookupOption_LOOKUP_SHORTER } else if args[0] == "validation" { if r != CMD_ADJ_IN { return fmt.Errorf("RPKI information is supported for only adj-in.") @@ -741,14 +763,14 @@ func showNeighborRib(r string, name string, args []string) error { } args = args[1:] } - filter = []*table.LookupPrefix{&table.LookupPrefix{ + filter = []*api.TableLookupPrefix{&api.TableLookupPrefix{ Prefix: target, LookupOption: option, }, } } - var rib *table.Table + var rib *api.Table switch r { case CMD_GLOBAL: rib, err = client.GetRIB(family, filter) @@ -770,7 +792,7 @@ func showNeighborRib(r string, name string, args []string) error { switch r { case CMD_LOCAL, CMD_ADJ_IN, CMD_ACCEPTED, CMD_REJECTED, CMD_ADJ_OUT: - if rib.Info("", 0).NumDestination == 0 { + if len(rib.Destinations) == 0 { peer, err := client.GetNeighbor(name, false) if err != nil { return err @@ -782,9 +804,9 @@ func showNeighborRib(r string, name string, args []string) error { } if globalOpts.Json { - d := make(map[string]*table.Destination) + d := make(map[string]*api.Destination) for _, dst := range rib.GetDestinations() { - d[dst.GetNlri().String()] = dst + d[dst.Prefix] = dst } j, _ := json.Marshal(d) fmt.Println(string(j)) @@ -793,44 +815,67 @@ func showNeighborRib(r string, name string, args []string) error { if validationTarget != "" { // show RPKI validation info - addr, _, err := net.ParseCIDR(validationTarget) - if err != nil { - return err - } - var nlri bgp.AddrPrefixInterface - if addr.To16() == nil { - nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, validationTarget) - } else { - nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, validationTarget) - } - d := rib.GetDestination(nlri) + d := func() *api.Destination { + for _, dst := range rib.GetDestinations() { + if dst.Prefix == validationTarget { + return dst + } + } + return nil + }() if d == nil { fmt.Println("Network not in table") return nil } shownAs := make(map[uint32]struct{}) - for _, p := range d.GetAllKnownPathList() { + for _, p := range d.GetPaths() { if err := showValidationInfo(p, shownAs); err != nil { return err } } } else { // show RIB - var ds [][]*table.Path - for _, d := range rib.GetSortedDestinations() { - var ps []*table.Path + dsts := rib.GetDestinations() + switch family { + case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: + type d struct { + prefix net.IP + dst *api.Destination + } + l := make([]*d, 0, len(dsts)) + for _, dst := range dsts { + _, p, _ := net.ParseCIDR(dst.Prefix) + l = append(l, &d{prefix: p.IP, dst: dst}) + } + + sort.Slice(l, func(i, j int) bool { + return bytes.Compare(l[i].prefix, l[j].prefix) < 0 + }) + + dsts = make([]*api.Destination, 0, len(dsts)) + for _, s := range l { + dsts = append(dsts, s.dst) + } + } + + for _, d := range dsts { switch r { case CMD_ACCEPTED: - ps = append(ps, d.GetAllKnownPathList()...) + l := make([]*api.Path, 0, len(d.Paths)) + for _, p := range d.GetPaths() { + if !p.Filtered { + l = append(l, p) + } + } + d.Paths = l case CMD_REJECTED: // always nothing + d.Paths = []*api.Path{} default: - ps = d.GetAllKnownPathList() } - ds = append(ds, ps) } - if len(ds) > 0 { - showRoute(ds, showAge, showBest, showLabel, showIdentifier) + if len(dsts) > 0 { + showRoute(dsts, showAge, showBest, showLabel, showIdentifier) } else { fmt.Println("Network not in table") } diff --git a/gobgp/cmd/rpki.go b/gobgp/cmd/rpki.go index a0423f58..aed144e2 100644 --- a/gobgp/cmd/rpki.go +++ b/gobgp/cmd/rpki.go @@ -91,11 +91,10 @@ func showRPKITable(args []string) error { } fmt.Printf(format, "Network", "Maxlen", "AS", "Server") for _, r := range roas { - host, _, _ := net.SplitHostPort(r.Src) - if len(args) > 0 && args[0] != host { + if len(args) > 0 && args[0] != r.Conf.Address { continue } - fmt.Printf(format, r.Prefix.String(), fmt.Sprint(r.MaxLen), fmt.Sprint(r.AS), r.Src) + fmt.Printf(format, r.Prefix, fmt.Sprint(r.Maxlen), fmt.Sprint(r.As), net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort)) } return nil } diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index 145f7d99..01251167 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -1090,6 +1090,34 @@ type AddrPrefixInterface interface { SetPathLocalIdentifier(uint32) } +func LabelString(nlri AddrPrefixInterface) string { + label := "" + switch n := nlri.(type) { + case *LabeledIPAddrPrefix: + label = n.Labels.String() + case *LabeledIPv6AddrPrefix: + label = n.Labels.String() + case *LabeledVPNIPAddrPrefix: + label = n.Labels.String() + case *LabeledVPNIPv6AddrPrefix: + label = n.Labels.String() + case *EVPNNLRI: + switch route := n.RouteTypeData.(type) { + case *EVPNEthernetAutoDiscoveryRoute: + label = fmt.Sprintf("[%d]", route.Label) + case *EVPNMacIPAdvertisementRoute: + var l []string + for _, i := range route.Labels { + l = append(l, strconv.Itoa(int(i))) + } + label = fmt.Sprintf("[%s]", strings.Join(l, ",")) + case *EVPNIPPrefixRoute: + label = fmt.Sprintf("[%d]", route.Label) + } + } + return label +} + type PrefixDefault struct { id uint32 localId uint32 @@ -5271,6 +5299,44 @@ type AsPathParamInterface interface { String() string } +func AsPathString(aspath *PathAttributeAsPath) string { + s := bytes.NewBuffer(make([]byte, 0, 64)) + for i, param := range aspath.Value { + segType := param.GetType() + asList := param.GetAS() + if i != 0 { + s.WriteString(" ") + } + + sep := " " + switch segType { + case BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + s.WriteString("(") + case BGP_ASPATH_ATTR_TYPE_CONFED_SET: + s.WriteString("[") + sep = "," + case BGP_ASPATH_ATTR_TYPE_SET: + s.WriteString("{") + sep = "," + } + for j, as := range asList { + s.WriteString(fmt.Sprintf("%d", as)) + if j != len(asList)-1 { + s.WriteString(sep) + } + } + switch segType { + case BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + s.WriteString(")") + case BGP_ASPATH_ATTR_TYPE_CONFED_SET: + s.WriteString("]") + case BGP_ASPATH_ATTR_TYPE_SET: + s.WriteString("}") + } + } + return s.String() +} + type AsPathParam struct { Type uint8 Num uint8 diff --git a/server/server.go b/server/server.go index 2293756d..6faecba9 100644 --- a/server/server.go +++ b/server/server.go @@ -2851,7 +2851,7 @@ func (w *Watcher) Generate(t WatchEventType) error { pathList := func() map[string][]*table.Path { pathList := make(map[string][]*table.Path) for _, t := range rib.Tables { - for _, dst := range t.GetSortedDestinations() { + for _, dst := range t.GetDestinations() { if paths := dst.GetKnownPathList(id, as); len(paths) > 0 { pathList[dst.GetNlri().String()] = clonePathList(paths) } diff --git a/table/path.go b/table/path.go index fa26f2e3..1cb81a91 100644 --- a/table/path.go +++ b/table/path.go @@ -22,8 +22,6 @@ import ( "math" "net" "sort" - "strconv" - "strings" "time" log "github.com/sirupsen/logrus" @@ -610,39 +608,7 @@ func (path *Path) GetAsPathLen() int { func (path *Path) GetAsString() string { s := bytes.NewBuffer(make([]byte, 0, 64)) if aspath := path.GetAsPath(); aspath != nil { - for i, param := range aspath.Value { - segType := param.GetType() - asList := param.GetAS() - if i != 0 { - s.WriteString(" ") - } - - sep := " " - switch segType { - case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: - s.WriteString("(") - case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: - s.WriteString("[") - sep = "," - case bgp.BGP_ASPATH_ATTR_TYPE_SET: - s.WriteString("{") - sep = "," - } - for j, as := range asList { - s.WriteString(fmt.Sprintf("%d", as)) - if j != len(asList)-1 { - s.WriteString(sep) - } - } - switch segType { - case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: - s.WriteString(")") - case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: - s.WriteString("]") - case bgp.BGP_ASPATH_ATTR_TYPE_SET: - s.WriteString("}") - } - } + return bgp.AsPathString(aspath) } return s.String() } @@ -677,31 +643,7 @@ func (path *Path) getAsListOfSpecificType(getAsSeq, getAsSet bool) []uint32 { } 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 + return bgp.LabelString(path.GetNlri()) } // PrependAsn prepends AS number. diff --git a/table/table.go b/table/table.go index 9d8edf40..82259b0f 100644 --- a/table/table.go +++ b/table/table.go @@ -18,7 +18,6 @@ package table import ( "fmt" "net" - "sort" "strings" "unsafe" @@ -190,27 +189,6 @@ func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination { return dest } -func (t *Table) GetSortedDestinations() []*Destination { - results := make([]*Destination, 0, len(t.GetDestinations())) - switch t.routeFamily { - case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: - r := radix.New() - for _, dst := range t.GetDestinations() { - r.Insert(AddrToRadixkey(dst.nlri), dst) - } - r.Walk(func(s string, v interface{}) bool { - results = append(results, v.(*Destination)) - return false - }) - default: - for _, dst := range t.GetDestinations() { - results = append(results, dst) - } - sort.Sort(destinations(results)) - } - return results -} - func (t *Table) GetDestinations() map[string]*Destination { return t.destinations } |