diff options
-rw-r--r-- | gobgp/cmd/neighbor.go | 24 | ||||
-rw-r--r-- | server/server.go | 64 |
2 files changed, 61 insertions, 27 deletions
diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index d8079449..55aaa959 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -400,27 +400,23 @@ func showNeighborRib(r string, name string, args []string) error { var prefix string var host net.IP + arg := &api.Table{ + Type: resource, + Family: uint32(rf), + Name: name, + } + if len(args) > 0 { if rf != bgp.RF_IPv4_UC && rf != bgp.RF_IPv6_UC { return fmt.Errorf("route filtering is only supported for IPv4/IPv6 unicast routes") } - _, p, err := net.ParseCIDR(args[0]) - if err != nil { - host = net.ParseIP(args[0]) - if host == nil { - return err - } - } else { - prefix = p.String() + arg.Destinations = []*api.Destination{ + &api.Destination{ + Prefix: args[0], + }, } } - arg := &api.Table{ - Type: resource, - Family: uint32(rf), - Name: name, - } - rib, err := client.GetRib(context.Background(), arg) if err != nil { return err diff --git a/server/server.go b/server/server.go index 7b6ffb3b..db92981a 100644 --- a/server/server.go +++ b/server/server.go @@ -1418,16 +1418,43 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { } rib = peer.localRib } - rf := bgp.RouteFamily(arg.Family) - if t, ok := rib.Tables[rf]; ok { - switch rf { - case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: - d.Destinations = sortedDsts(rib.Tables[rf]) - default: - d.Destinations = make([]*api.Destination, 0, len(t.GetDestinations())) - for _, dst := range t.GetDestinations() { - d.Destinations = append(d.Destinations, dst.ToApiStruct()) + af := bgp.RouteFamily(arg.Family) + if _, ok := rib.Tables[af]; !ok { + err = fmt.Errorf("address family: %s not supported", af) + goto ERROR + } + + switch af { + case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: + if len(arg.Destinations) > 0 { + dsts := []*api.Destination{} + for _, dst := range arg.Destinations { + key := dst.Prefix + if _, prefix, err := net.ParseCIDR(key); err == nil { + if dst := rib.Tables[af].GetDestination(prefix.String()); dst != nil { + dsts = append(dsts, dst.ToApiStruct()) + } + } else if host := net.ParseIP(key); host != nil { + masklen := 32 + if af == bgp.RF_IPv6_UC { + masklen = 128 + } + for i := masklen; i > 0; i-- { + if dst := rib.Tables[af].GetDestination(fmt.Sprintf("%s/%d", key, i)); dst != nil { + dsts = append(dsts, dst.ToApiStruct()) + break + } + } + } } + d.Destinations = dsts + } else { + d.Destinations = sortedDsts(rib.Tables[af]) + } + default: + d.Destinations = make([]*api.Destination, 0, len(rib.Tables[af].GetDestinations())) + for _, dst := range rib.Tables[af].GetDestinations() { + d.Destinations = append(d.Destinations, dst.ToApiStruct()) } } grpcReq.ResponseCh <- &GrpcResponse{ @@ -1494,10 +1521,21 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg { r := radix.New() for _, p := range paths { key := p.GetNlri().String() - r.Insert(table.CidrToRadixkey(key), &api.Destination{ - Prefix: key, - Paths: []*api.Path{p.ToApiStruct()}, - }) + found := true + for _, dst := range arg.Destinations { + found = false + if dst.Prefix == key { + found = true + break + } + } + + if found { + r.Insert(table.CidrToRadixkey(key), &api.Destination{ + Prefix: key, + Paths: []*api.Path{p.ToApiStruct()}, + }) + } } r.Walk(func(s string, v interface{}) bool { results = append(results, v.(*api.Destination)) |