diff options
-rw-r--r-- | api/gobgp.pb.go | 58 | ||||
-rw-r--r-- | api/gobgp.proto | 13 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 32 | ||||
-rw-r--r-- | server/grpc_server.go | 9 | ||||
-rw-r--r-- | server/server.go | 61 | ||||
-rw-r--r-- | table/path.go | 1 |
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 { |