diff options
-rw-r--r-- | api/grpc_server.go | 34 | ||||
-rw-r--r-- | client/client.go | 17 | ||||
-rw-r--r-- | gobgp/cmd/common.go | 6 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 100 |
4 files changed, 122 insertions, 35 deletions
diff --git a/api/grpc_server.go b/api/grpc_server.go index 1d8cca6a..54fd01ec 100644 --- a/api/grpc_server.go +++ b/api/grpc_server.go @@ -874,21 +874,7 @@ func (s *Server) GetRoa(ctx context.Context, arg *GetRoaRequest) (*GetRoaRespons if err != nil { return nil, err } - l := make([]*Roa, 0, len(roas)) - for _, r := range roas { - host, port, _ := net.SplitHostPort(r.Src) - l = append(l, &Roa{ - As: r.AS, - Maxlen: uint32(r.MaxLen), - Prefixlen: uint32(r.Prefix.Length), - Prefix: r.Prefix.Prefix.String(), - Conf: &RPKIConf{ - Address: host, - RemotePort: port, - }, - }) - } - return &GetRoaResponse{Roas: l}, nil + return &GetRoaResponse{Roas: NewRoaListFromTableStructList(roas)}, nil } func (s *Server) EnableZebra(ctx context.Context, arg *EnableZebraRequest) (*EnableZebraResponse, error) { @@ -2077,6 +2063,24 @@ func NewPolicyFromApiStruct(a *Policy) (*table.Policy, error) { }, nil } +func NewRoaListFromTableStructList(origin []*table.ROA) []*Roa { + l := make([]*Roa, 0) + for _, r := range origin { + host, port, _ := net.SplitHostPort(r.Src) + l = append(l, &Roa{ + As: r.AS, + Maxlen: uint32(r.MaxLen), + Prefixlen: uint32(r.Prefix.Length), + Prefix: r.Prefix.Prefix.String(), + Conf: &RPKIConf{ + Address: host, + RemotePort: port, + }, + }) + } + return l +} + func (s *Server) GetPolicy(ctx context.Context, arg *GetPolicyRequest) (*GetPolicyResponse, error) { l := make([]*Policy, 0) for _, p := range s.bgpServer.GetPolicy() { diff --git a/client/client.go b/client/client.go index b9faf6ba..e8108c64 100644 --- a/client/client.go +++ b/client/client.go @@ -22,12 +22,13 @@ import ( "strconv" "time" + "golang.org/x/net/context" + "google.golang.org/grpc" + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - "golang.org/x/net/context" - "google.golang.org/grpc" ) type Client struct { @@ -841,17 +842,7 @@ func (cli *Client) GetROA(family bgp.RouteFamily) ([]*table.ROA, error) { if err != nil { return nil, err } - roas := make([]*table.ROA, 0, len(rsp.Roas)) - for _, r := range rsp.Roas { - ip := net.ParseIP(r.Prefix) - if ip.To4() != nil { - ip = ip.To4() - } - 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 + return api.NewROAListFromApiStructList(rsp.Roas), nil } func (cli *Client) AddRPKIServer(address string, port, lifetime int) error { diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go index 124c2b99..53c17604 100644 --- a/gobgp/cmd/common.go +++ b/gobgp/cmd/common.go @@ -26,12 +26,13 @@ import ( "strings" "time" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + cli "github.com/osrg/gobgp/client" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" ) const ( @@ -78,6 +79,7 @@ const ( CMD_BMP = "bmp" CMD_LARGECOMMUNITY = "large-community" CMD_SUMMARY = "summary" + CMD_VALIDATION = "validation" ) var subOpts struct { diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 3c6b5669..bd957097 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -549,6 +549,71 @@ func ShowRoute(pathList []*table.Path, showAge, showBest, showLabel, showIdentif } } +func checkOriginAsWasNotShown(p *table.Path, shownAs map[uint32]struct{}) bool { + asPath := p.GetAsPath().Value + // the path was generated in internal + if len(asPath) == 0 { + return false + } + aslist := asPath[len(asPath)-1].(*bgp.As4PathParam).AS + origin := aslist[len(aslist)-1] + + if _, ok := shownAs[origin]; ok { + return false + } + shownAs[origin] = struct{}{} + return true +} + +func ShowValidationInfo(p *table.Path) { + status := p.Validation().Status + reason := p.Validation().Reason + asPath := p.GetAsPath().Value + aslist := asPath[len(asPath)-1].(*bgp.As4PathParam).AS + origin := aslist[len(aslist)-1] + + fmt.Printf("Target Prefix: %s, AS: %d\n", p.GetNlri().String(), origin) + fmt.Printf(" This route is %s", status) + switch status { + case config.RPKI_VALIDATION_RESULT_TYPE_INVALID: + fmt.Printf(" reason: %s\n", reason) + switch reason { + case table.RPKI_VALIDATION_REASON_TYPE_AS: + fmt.Println(" No VRP ASN matches the route origin ASN.") + case table.RPKI_VALIDATION_REASON_TYPE_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: + fmt.Println("\n No VRP Covers the Route Prefix") + default: + fmt.Print("\n\n") + } + + printVRPs := func(l []*table.ROA) { + if len(l) == 0 { + fmt.Println(" No Entry") + } else { + var format string + if ip, _, _ := net.ParseCIDR(p.GetNlri().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.Println(" Matched VRPs: ") + printVRPs(p.Validation().Matched) + fmt.Println(" Unmatched AS VRPs: ") + printVRPs(p.Validation().UnmatchedAs) + fmt.Println(" Unmatched Length VRPs: ") + printVRPs(p.Validation().UnmatchedLength) +} + func showRibInfo(r, name string) error { def := addr2AddressFamily(net.ParseIP(name)) if r == CMD_GLOBAL { @@ -605,6 +670,8 @@ func showNeighborRib(r string, name string, args []string) error { showAge := true showLabel := false showIdentifier := false + validationTarget := "" + def := addr2AddressFamily(net.ParseIP(name)) switch r { case CMD_GLOBAL: @@ -628,21 +695,29 @@ func showNeighborRib(r string, name string, args []string) error { var filter []*table.LookupPrefix if len(args) > 0 { + target := args[0] if _, _, err = parseCIDRorIP(args[0]); err != nil { return err } var option table.LookupOption - if len(args) > 1 { - if args[1] == "longer-prefixes" { + args = args[1:] + for len(args) != 0 { + if args[0] == "longer-prefixes" { option = table.LOOKUP_LONGER - } else if args[1] == "shorter-prefixes" { + } else if args[0] == "shorter-prefixes" { option = table.LOOKUP_SHORTER + } else if args[0] == "validation" { + if r != CMD_ADJ_IN { + return fmt.Errorf("RPKI information is supported for only adj-in.") + } + validationTarget = target } else { return fmt.Errorf("invalid format for route filtering") } + args = args[1:] } filter = []*table.LookupPrefix{&table.LookupPrefix{ - Prefix: args[0], + Prefix: target, LookupOption: option, }, } @@ -687,8 +762,12 @@ func showNeighborRib(r string, name string, args []string) error { return nil } + shownAs := make(map[uint32]struct{}) counter := 0 for _, d := range rib.GetSortedDestinations() { + if validationTarget != "" && d.GetNlri().String() != validationTarget { + continue + } var ps []*table.Path if r == CMD_ACCEPTED || r == CMD_REJECTED { for _, p := range d.GetAllKnownPathList() { @@ -711,7 +790,18 @@ func showNeighborRib(r string, name string, args []string) error { if counter == 0 { showHeader = true } - ShowRoute(ps, showAge, showBest, showLabel, showIdentifier, false, showHeader) + if validationTarget != "" { + for _, p := range ps { + asPath := p.GetAsPath().Value + if len(asPath) == 0 { + fmt.Printf("The path to %s was locally generated.\n", p.GetNlri().String()) + } else if checkOriginAsWasNotShown(p, shownAs) { + ShowValidationInfo(p) + } + } + } else { + ShowRoute(ps, showAge, showBest, showLabel, showIdentifier, false, showHeader) + } counter++ } |