summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-12-26 19:24:46 -0800
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-12-26 19:24:46 -0800
commit7a2b3951160804c6895714621099168e8e56aa74 (patch)
treef847e72ac7fc6064774f5de1afca77c712d5809d
parent01157e466a510a9d7c7290c26a131734e7566261 (diff)
add MOD_PATH API
Handle only one route unlike MOD_PATHS API. When the API returns an uuid when a route is created. The uuid can be used to remove the route later. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go58
-rw-r--r--api/gobgp.proto13
-rw-r--r--gobgp/cmd/global.go32
-rw-r--r--server/grpc_server.go9
-rw-r--r--server/server.go61
-rw-r--r--table/path.go1
6 files changed, 149 insertions, 25 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index 92404f9b..14f0b3b5 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -11,6 +11,8 @@ It is generated from these files:
It has these top-level messages:
Error
Arguments
+ ModPathArguments
+ ModPathResponse
ModPathsArguments
ModNeighborArguments
MrtArguments
@@ -348,6 +350,33 @@ func (m *Arguments) Reset() { *m = Arguments{} }
func (m *Arguments) String() string { return proto.CompactTextString(m) }
func (*Arguments) ProtoMessage() {}
+type ModPathArguments struct {
+ Operation Operation `protobuf:"varint,1,opt,name=operation,enum=gobgpapi.Operation" json:"operation,omitempty"`
+ Resource Resource `protobuf:"varint,2,opt,name=resource,enum=gobgpapi.Resource" json:"resource,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"`
+ Path *Path `protobuf:"bytes,4,opt,name=path" json:"path,omitempty"`
+ Uuid []byte `protobuf:"bytes,5,opt,name=uuid,proto3" json:"uuid,omitempty"`
+}
+
+func (m *ModPathArguments) Reset() { *m = ModPathArguments{} }
+func (m *ModPathArguments) String() string { return proto.CompactTextString(m) }
+func (*ModPathArguments) ProtoMessage() {}
+
+func (m *ModPathArguments) GetPath() *Path {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+type ModPathResponse struct {
+ Uuid []byte `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+}
+
+func (m *ModPathResponse) Reset() { *m = ModPathResponse{} }
+func (m *ModPathResponse) String() string { return proto.CompactTextString(m) }
+func (*ModPathResponse) ProtoMessage() {}
+
type ModPathsArguments struct {
Resource Resource `protobuf:"varint,1,opt,name=resource,enum=gobgpapi.Resource" json:"resource,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
@@ -1190,6 +1219,8 @@ func (*Global) ProtoMessage() {}
func init() {
proto.RegisterType((*Error)(nil), "gobgpapi.Error")
proto.RegisterType((*Arguments)(nil), "gobgpapi.Arguments")
+ proto.RegisterType((*ModPathArguments)(nil), "gobgpapi.ModPathArguments")
+ proto.RegisterType((*ModPathResponse)(nil), "gobgpapi.ModPathResponse")
proto.RegisterType((*ModPathsArguments)(nil), "gobgpapi.ModPathsArguments")
proto.RegisterType((*ModNeighborArguments)(nil), "gobgpapi.ModNeighborArguments")
proto.RegisterType((*MrtArguments)(nil), "gobgpapi.MrtArguments")
@@ -1269,6 +1300,7 @@ type GobgpApiClient interface {
Shutdown(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error)
Enable(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error)
Disable(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (*Error, error)
+ ModPath(ctx context.Context, in *ModPathArguments, opts ...grpc.CallOption) (*ModPathResponse, error)
ModPaths(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModPathsClient, error)
MonitorBestChanged(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorBestChangedClient, error)
MonitorPeerState(ctx context.Context, in *Arguments, opts ...grpc.CallOption) (GobgpApi_MonitorPeerStateClient, error)
@@ -1440,6 +1472,15 @@ func (c *gobgpApiClient) Disable(ctx context.Context, in *Arguments, opts ...grp
return out, nil
}
+func (c *gobgpApiClient) ModPath(ctx context.Context, in *ModPathArguments, opts ...grpc.CallOption) (*ModPathResponse, error) {
+ out := new(ModPathResponse)
+ err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/ModPath", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *gobgpApiClient) ModPaths(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_ModPathsClient, error) {
stream, err := grpc.NewClientStream(ctx, &_GobgpApi_serviceDesc.Streams[1], c.cc, "/gobgpapi.GobgpApi/ModPaths", opts...)
if err != nil {
@@ -1877,6 +1918,7 @@ type GobgpApiServer interface {
Shutdown(context.Context, *Arguments) (*Error, error)
Enable(context.Context, *Arguments) (*Error, error)
Disable(context.Context, *Arguments) (*Error, error)
+ ModPath(context.Context, *ModPathArguments) (*ModPathResponse, error)
ModPaths(GobgpApi_ModPathsServer) error
MonitorBestChanged(*Arguments, GobgpApi_MonitorBestChangedServer) error
MonitorPeerState(*Arguments, GobgpApi_MonitorPeerStateServer) error
@@ -2069,6 +2111,18 @@ func _GobgpApi_Disable_Handler(srv interface{}, ctx context.Context, dec func(in
return out, nil
}
+func _GobgpApi_ModPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
+ in := new(ModPathArguments)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ out, err := srv.(GobgpApiServer).ModPath(ctx, in)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func _GobgpApi_ModPaths_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(GobgpApiServer).ModPaths(&gobgpApiModPathsServer{stream})
}
@@ -2469,6 +2523,10 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{
Handler: _GobgpApi_Disable_Handler,
},
{
+ MethodName: "ModPath",
+ Handler: _GobgpApi_ModPath_Handler,
+ },
+ {
MethodName: "ModMrt",
Handler: _GobgpApi_ModMrt_Handler,
},
diff --git a/api/gobgp.proto b/api/gobgp.proto
index c34ac23b..296d7f18 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -33,6 +33,7 @@ service GobgpApi {
rpc Shutdown(Arguments) returns (Error) {}
rpc Enable(Arguments) returns (Error) {}
rpc Disable(Arguments) returns (Error) {}
+ rpc ModPath(ModPathArguments) returns (ModPathResponse) {}
rpc ModPaths(stream ModPathsArguments) returns (Error) {}
rpc MonitorBestChanged(Arguments) returns (stream Destination) {}
rpc MonitorPeerState(Arguments) returns (stream Peer) {}
@@ -71,6 +72,18 @@ message Arguments {
string name = 3;
}
+message ModPathArguments {
+ Operation operation = 1;
+ Resource resource = 2;
+ string name = 3;
+ Path path = 4;
+ bytes uuid = 5;
+}
+
+message ModPathResponse {
+ bytes uuid = 1;
+}
+
message ModPathsArguments {
Resource resource = 1;
string name = 2;
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go
index fec152b5..a31556b9 100644
--- a/gobgp/cmd/global.go
+++ b/gobgp/cmd/global.go
@@ -646,33 +646,19 @@ usage: %s rib %s match <MATCH_EXPR> then <THEN_EXPR> -a %%s
return err
}
- if modtype == CMD_DEL {
- path.IsWithdraw = true
+ arg := &api.ModPathArguments{
+ Operation: api.Operation_ADD,
+ Resource: resource,
+ Name: name,
+ Path: path,
}
- arg := &api.ModPathsArguments{
- Resource: resource,
- Name: name,
- Paths: []*api.Path{path},
+ if modtype == CMD_DEL {
+ arg.Operation = api.Operation_DEL
}
- stream, err := client.ModPaths(context.Background())
- if err != nil {
- return err
- }
- err = stream.Send(arg)
- if err != nil {
- return err
- }
- stream.CloseSend()
- res, e := stream.CloseAndRecv()
- if e != nil {
- return e
- }
- if res.Code != api.Error_SUCCESS {
- return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
- }
- return nil
+ _, err = client.ModPath(context.Background(), arg)
+ return err
}
func showGlobalConfig(args []string) error {
diff --git a/server/grpc_server.go b/server/grpc_server.go
index e2c1a0b5..776f64da 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -55,6 +55,7 @@ const (
REQ_VRF
REQ_VRFS
REQ_VRF_MOD
+ REQ_MOD_PATH
REQ_MOD_PATHS
REQ_DEFINED_SET
REQ_MOD_DEFINED_SET
@@ -211,6 +212,14 @@ func (s *Server) Disable(ctx context.Context, arg *api.Arguments) (*api.Error, e
return s.neighbor(REQ_NEIGHBOR_DISABLE, arg)
}
+func (s *Server) ModPath(ctx context.Context, arg *api.ModPathArguments) (*api.ModPathResponse, error) {
+ d, err := s.get(REQ_MOD_PATH, arg)
+ if err != nil {
+ return nil, err
+ }
+ return d.(*api.ModPathResponse), nil
+}
+
func (s *Server) ModPaths(stream api.GobgpApi_ModPathsServer) error {
for {
arg, err := stream.Recv()
diff --git a/server/server.go b/server/server.go
index 893229c2..670deee4 100644
--- a/server/server.go
+++ b/server/server.go
@@ -26,6 +26,7 @@ import (
"github.com/osrg/gobgp/packet"
"github.com/osrg/gobgp/table"
"github.com/osrg/gobgp/zebra"
+ "github.com/satori/go.uuid"
"net"
"os"
"strconv"
@@ -1204,6 +1205,58 @@ func (server *BgpServer) Api2PathList(resource api.Resource, name string, ApiPat
func (server *BgpServer) handleModPathRequest(grpcReq *GrpcRequest) []*table.Path {
var err error
+ var uuidBytes []byte
+ paths := make([]*table.Path, 0, 1)
+ arg, ok := grpcReq.Data.(*api.ModPathArguments)
+ if !ok {
+ err = fmt.Errorf("type assertion failed")
+ }
+
+ if err == nil {
+ switch arg.Operation {
+ case api.Operation_DEL:
+ if len(arg.Uuid) > 0 {
+ path := func() *table.Path {
+ for _, rf := range server.globalRib.GetRFlist() {
+ for _, path := range server.globalRib.GetPathList(table.GLOBAL_RIB_NAME, rf) {
+ if len(path.Uuid) > 0 && bytes.Equal(path.Uuid, arg.Uuid) {
+ return path
+ }
+ }
+ }
+ return nil
+ }()
+ if path != nil {
+ paths = append(paths, path.Clone(path.Owner, true))
+ } else {
+ err = fmt.Errorf("Can't find a specified path")
+ }
+ break
+ }
+ arg.Path.IsWithdraw = true
+ fallthrough
+ case api.Operation_ADD:
+ paths, err = server.Api2PathList(arg.Resource, arg.Name, []*api.Path{arg.Path})
+ if err == nil {
+ u := uuid.NewV4()
+ uuidBytes = u.Bytes()
+ paths[0].Uuid = uuidBytes
+ }
+ }
+ }
+ result := &GrpcResponse{
+ ResponseErr: err,
+ Data: &api.ModPathResponse{
+ Uuid: uuidBytes,
+ },
+ }
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return paths
+}
+
+func (server *BgpServer) handleModPathsRequest(grpcReq *GrpcRequest) []*table.Path {
+ var err error
var paths []*table.Path
arg, ok := grpcReq.Data.(*api.ModPathsArguments)
if !ok {
@@ -1531,14 +1584,18 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
Data: d,
}
close(grpcReq.ResponseCh)
- case REQ_MOD_PATHS:
+ case REQ_MOD_PATH:
pathList := server.handleModPathRequest(grpcReq)
if len(pathList) > 0 {
msgs, _ = server.propagateUpdate(nil, pathList)
+ }
+ case REQ_MOD_PATHS:
+ pathList := server.handleModPathsRequest(grpcReq)
+ if len(pathList) > 0 {
+ msgs, _ = server.propagateUpdate(nil, pathList)
grpcReq.ResponseCh <- &GrpcResponse{}
close(grpcReq.ResponseCh)
}
-
case REQ_NEIGHBORS:
results := make([]*GrpcResponse, len(server.neighborMap))
i := 0
diff --git a/table/path.go b/table/path.go
index 6812a184..df84645a 100644
--- a/table/path.go
+++ b/table/path.go
@@ -42,6 +42,7 @@ type Path struct {
reason BestPathReason
filtered map[string]PolicyDirection
key string
+ Uuid []byte
}
func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, medSetByTargetNeighbor bool, timestamp time.Time, noImplicitWithdraw bool) *Path {