diff --git a/manager/manager.go b/manager/manager.go index 732e33c..d04bacf 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -69,6 +69,9 @@ type Config struct { Sync func(string) // Timeout defines the optional duration to wait for a gRPC dial. Timeout time.Duration + // ReceiveTimeout defines the optional duration to wait for receiving from + // a target. 0 means timeout is disabled. + ReceiveTimeout time.Duration // Update will be invoked in response to gNMI updates. Update func(string, *gpb.Notification) // ConnectionManager is used to create gRPC connections. @@ -99,6 +102,7 @@ type Manager struct { sync func(string) testSync func() // exposed for test synchronization timeout time.Duration + receiveTimeout time.Duration update func(string, *gpb.Notification) mu sync.Mutex @@ -134,6 +138,7 @@ func NewManager(cfg Config) (*Manager, error) { targets: make(map[string]*target), testSync: func() {}, timeout: cfg.Timeout, + receiveTimeout: cfg.ReceiveTimeout, update: cfg.Update, }, nil } @@ -191,11 +196,30 @@ func (m *Manager) createConn(ctx context.Context, name string, t *tpb.Target) (c } } -func (m *Manager) handleUpdates(name string, sc gpb.GNMI_SubscribeClient) error { +func (m *Manager) handleUpdates(ctx context.Context, name string, sc gpb.GNMI_SubscribeClient) error { defer m.testSync() connected := false + var recvTimer *time.Timer + if m.receiveTimeout.Nanoseconds() > 0 { + recvTimer = time.NewTimer(m.receiveTimeout) + recvTimer.Stop() + go func() { + select { + case <-ctx.Done(): + case <-recvTimer.C: + log.Errorf("Timed out waiting to receive from %q after %v", name, m.receiveTimeout) + m.Reconnect(name) + } + }() + } for { + if recvTimer != nil { + recvTimer.Reset(m.receiveTimeout) + } resp, err := sc.Recv() + if recvTimer != nil { + recvTimer.Stop() + } if err != nil { if m.reset != nil { m.reset(name) @@ -238,7 +262,7 @@ func (m *Manager) subscribe(ctx context.Context, name string, conn *grpc.ClientC if err := sc.Send(cr); err != nil { return fmt.Errorf("error sending subscription request to target %q: %v", name, err) } - if err = m.handleUpdates(name, sc); err != nil { + if err = m.handleUpdates(ctx, name, sc); err != nil { return fmt.Errorf("stream failed for target %q: %v", name, err) } return nil diff --git a/manager/manager_test.go b/manager/manager_test.go index b908186..7922cc5 100644 --- a/manager/manager_test.go +++ b/manager/manager_test.go @@ -554,6 +554,87 @@ func TestRetrySubscribe(t *testing.T) { r.assertLast(t, "no recovery after remove", nil, nil, nil, 0) } +func TestReceiveTimeout(t *testing.T) { + f := newFakeConnection(t) + addr, stop := newDevice(t, &fakeServer{}) + defer stop() + + origSubscribeClient := subscribeClient + defer func() { subscribeClient = origSubscribeClient }() + fc := newFakeSubscribeClient() + subscribeClient = func(ctx context.Context, conn *grpc.ClientConn) (gpb.GNMI_SubscribeClient, error) { + go func() { + select { + case <-ctx.Done(): + fc.sendRecvErr() // Simulate stream closure. + } + }() + return fc, nil + } + + r := record{} + m, err := NewManager(Config{ + Credentials: &fakeCreds{}, + Timeout: time.Minute, + ReceiveTimeout: 2 * time.Second, + Connect: func(s string) { + r.connects = append(r.connects, s) + }, + ConnectionManager: f, + Sync: func(s string) { + r.syncs = append(r.syncs, s) + }, + Reset: func(s string) { + r.resets = append(r.resets, s) + }, + Update: func(_ string, g *gpb.Notification) { + r.updates = append(r.updates, g) + }, + }) + if err != nil { + t.Fatal("could not initialize Manager") + } + handleUpdateDoneOnce := make(chan struct{}) + handleUpdateCalled := make(chan struct{}, 1) + m.testSync = func() { + select { + case <-handleUpdateDoneOnce: + default: + close(handleUpdateDoneOnce) + } + handleUpdateCalled <- struct{}{} + } + + name := "device1" + err = m.Add(name, &tpb.Target{Addresses: []string{addr}}, validSubscribeRequest) + if err != nil { + t.Fatalf("got error adding: %v, want no error", err) + } + defer m.Remove(name) + + _, ok := m.targets[name] + if !ok { + t.Fatalf("missing internal target") + } + + <-handleUpdateDoneOnce // receive has timed out + <-handleUpdateCalled + r.assertLast(t, "after receive timeout", nil, nil, []string{name}, 0) // reset once + + // Verify manager will try reconnecting to target + fc.sendSync() + <-handleUpdateCalled + r.assertLast(t, "sync after reconnect", []string{name}, []string{name}, nil, 0) + + updateCount := 10 + for i := 0; i < updateCount; i++ { + fc.sendUpdate() + <-handleUpdateCalled + } + r.assertLast(t, "updates sent after reconnect", nil, nil, nil, updateCount) + assertTargets(t, m, 1) +} + func TestRemoveDuringBackoff(t *testing.T) { origBaseDelay, origMaxDelay := RetryBaseDelay, RetryMaxDelay defer func() { RetryBaseDelay, RetryMaxDelay = origBaseDelay, origMaxDelay }() diff --git a/proto/gnmi/gnmi.pb.go b/proto/gnmi/gnmi.pb.go index f03e240..12f42d3 100644 --- a/proto/gnmi/gnmi.pb.go +++ b/proto/gnmi/gnmi.pb.go @@ -1731,9 +1731,9 @@ func (x *SetRequest) GetExtension() []*gnmi_ext.Extension { // client. It reports the result of the modifications to the data tree that were // specified by the client. Errors for this RPC should be reported using the // https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto -// message in the RPC return. The gnmi.Error message can be used to add additional -// details where required. -// Reference: gNMI Specification Section 3.4.2 +// message in the RPC return. The gnmi.Error message can be used to add +// additional details where required. Reference: gNMI Specification +// Section 3.4.2 type SetResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2584,7 +2584,7 @@ var file_proto_gnmi_gnmi_proto_rawDesc = []byte{ 0x6e, 0x6d, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6e, 0x6d, - 0x69, 0xca, 0x3e, 0x05, 0x30, 0x2e, 0x38, 0x2e, 0x30, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x69, 0xca, 0x3e, 0x05, 0x30, 0x2e, 0x39, 0x2e, 0x30, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } diff --git a/proto/gnmi/gnmi.proto b/proto/gnmi/gnmi.proto index 79fee85..ba94072 100644 --- a/proto/gnmi/gnmi.proto +++ b/proto/gnmi/gnmi.proto @@ -37,7 +37,7 @@ extend google.protobuf.FileOptions { // gNMI_service is the current version of the gNMI service, returned through // the Capabilities RPC. -option (gnmi_service) = "0.8.0"; +option (gnmi_service) = "0.9.0"; option go_package = "github.com/openconfig/gnmi/proto/gnmi"; option java_multiple_files = true; @@ -81,10 +81,10 @@ service gNMI { // whose value has changed in the data tree. // Reference: gNMI Specification Section 2.1 message Notification { - int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. - Path prefix = 2; // Prefix used for paths in the message. - repeated Update update = 4; // Data elements that have changed values. - repeated Path delete = 5; // Data elements that have been deleted. + int64 timestamp = 1; // Timestamp in nanoseconds since Epoch. + Path prefix = 2; // Prefix used for paths in the message. + repeated Update update = 4; // Data elements that have changed values. + repeated Path delete = 5; // Data elements that have been deleted. // This notification contains a set of paths that are always updated together // referenced by a globally unique prefix. bool atomic = 6; @@ -97,10 +97,10 @@ message Notification { // Value pair. // Reference: gNMI Specification Section 2.1 message Update { - Path path = 1; // The path (key) for the update. - Value value = 2 [deprecated=true]; // The value (value) for the update. - TypedValue val = 3; // The explicitly typed update value. - uint32 duplicates = 4; // Number of coalesced duplicates. + Path path = 1; // The path (key) for the update. + Value value = 2 [deprecated = true]; // The value (value) for the update. + TypedValue val = 3; // The explicitly typed update value. + uint32 duplicates = 4; // Number of coalesced duplicates. } // TypedValue is used to encode a value being sent between the client and @@ -112,14 +112,15 @@ message TypedValue { // encoding is a particular form of the base protobuf type, a specific // field is used to store the value (e.g., json_val). oneof value { - string string_val = 1; // String value. - int64 int_val = 2; // Integer value. - uint64 uint_val = 3; // Unsigned integer value. - bool bool_val = 4; // Bool value. - bytes bytes_val = 5; // Arbitrary byte sequence value. - float float_val = 6 [deprecated=true]; // Deprecated - use double_val. - double double_val = 14; // Floating point value. - Decimal64 decimal_val = 7 [deprecated=true]; // Deprecated - use double_val. + string string_val = 1; // String value. + int64 int_val = 2; // Integer value. + uint64 uint_val = 3; // Unsigned integer value. + bool bool_val = 4; // Bool value. + bytes bytes_val = 5; // Arbitrary byte sequence value. + float float_val = 6 [deprecated = true]; // Deprecated - use double_val. + double double_val = 14; // Floating point value. + Decimal64 decimal_val = 7 + [deprecated = true]; // Deprecated - use double_val. ScalarArray leaflist_val = 8; // Mixed type scalar array value. google.protobuf.Any any_val = 9; // protobuf.Any encoded bytes. bytes json_val = 10; // JSON-encoded text. @@ -140,19 +141,19 @@ message TypedValue { message Path { // Elements of the path are no longer encoded as a string, but rather within // the elem field as a PathElem message. - repeated string element = 1 [deprecated=true]; - string origin = 2; // Label to disambiguate path. - repeated PathElem elem = 3; // Elements of the path. - string target = 4; // The name of the target - // (Sec. 2.2.2.1) + repeated string element = 1 [deprecated = true]; + string origin = 2; // Label to disambiguate path. + repeated PathElem elem = 3; // Elements of the path. + string target = 4; // The name of the target + // (Sec. 2.2.2.1) } // PathElem encodes an element of a gNMI path, along with any attributes (keys) // that may be associated with it. // Reference: gNMI Specification Section 2.2.2. message PathElem { - string name = 1; // The name of the element in the path. - map key = 2; // Map of key (attribute) name to value. + string name = 1; // The name of the element in the path. + map key = 2; // Map of key (attribute) name to value. } // Value encodes a data tree node's value - along with the way in which @@ -160,8 +161,9 @@ message PathElem { // Reference: gNMI Specification Section 2.2.3. message Value { option deprecated = true; - bytes value = 1; // Value of the variable being transmitted. - Encoding type = 2; // Encoding used for the value field. + + bytes value = 1; // Value of the variable being transmitted. + Encoding type = 2; // Encoding used for the value field. } // Encoding defines the value encoding formats that are supported by the gNMI @@ -170,11 +172,11 @@ message Value { // data to be returned to the client (in both Subscribe and Get RPCs). // Reference: gNMI Specification Section 2.3 enum Encoding { - JSON = 0; // JSON encoded text. - BYTES = 1; // Arbitrarily encoded bytes. - PROTO = 2; // Encoded according to scalar values of TypedValue. - ASCII = 3; // ASCII text of an out-of-band agreed format. - JSON_IETF = 4; // JSON encoded text as per RFC7951. + JSON = 0; // JSON encoded text. + BYTES = 1; // Arbitrarily encoded bytes. + PROTO = 2; // Encoded according to scalar values of TypedValue. + ASCII = 3; // ASCII text of an out-of-band agreed format. + JSON_IETF = 4; // JSON encoded text as per RFC7951. } // Error message previously utilised to return errors to the client. Deprecated @@ -183,9 +185,10 @@ enum Encoding { // Reference: gNMI Specification Section 2.5 message Error { option deprecated = true; - uint32 code = 1; // Canonical gRPC error code. - string message = 2; // Human readable error. - google.protobuf.Any data = 3; // Optional additional information. + + uint32 code = 1; // Canonical gRPC error code. + string message = 2; // Human readable error. + google.protobuf.Any data = 3; // Optional additional information. } // Decimal64 is used to encode a fixed precision decimal number. The value @@ -195,8 +198,9 @@ message Error { // as double precision. message Decimal64 { option deprecated = true; - int64 digits = 1; // Set of digits. - uint32 precision = 2; // Number of digits following the decimal point. + + int64 digits = 1; // Set of digits. + uint32 precision = 2; // Number of digits following the decimal point. } // ScalarArray is used to encode a mixed-type array of values. @@ -214,8 +218,8 @@ message ScalarArray { // Reference: gNMI Specification Section 3.5.1.1 message SubscribeRequest { oneof request { - SubscriptionList subscribe = 1; // Specify the paths within a subscription. - Poll poll = 3; // Trigger a polled update. + SubscriptionList subscribe = 1; // Specify the paths within a subscription. + Poll poll = 3; // Trigger a polled update. } // Extension messages associated with the SubscribeRequest. See the // gNMI extension specification for further definition. @@ -229,8 +233,7 @@ message SubscribeRequest { // send telemetry updates for the paths that are associated with the // subscription. // Reference: gNMI Specification Section Section 3.5.1.4 -message Poll { -} +message Poll {} // SubscribeResponse is the message used by the target within a Subscribe RPC. // The target includes a Notification message which is used to transmit values @@ -240,12 +243,12 @@ message Poll { // Reference: gNMI Specification Section 3.5.1.4 message SubscribeResponse { oneof response { - Notification update = 1; // Changed or sampled value for a path. + Notification update = 1; // Changed or sampled value for a path. // Indicate target has sent all values associated with the subscription // at least once. bool sync_response = 3; // Deprecated in favour of google.golang.org/genproto/googleapis/rpc/status - Error error = 4 [deprecated=true]; + Error error = 4 [deprecated = true]; } // Extension messages associated with the SubscribeResponse. See the // gNMI extension specification for further definition. @@ -258,14 +261,14 @@ message SubscribeResponse { // subscription. // Reference: gNMI Specification Section 3.5.1.2 message SubscriptionList { - Path prefix = 1; // Prefix used for paths. - repeated Subscription subscription = 2; // Set of subscriptions to create. - QOSMarking qos = 4; // DSCP marking to be used. + Path prefix = 1; // Prefix used for paths. + repeated Subscription subscription = 2; // Set of subscriptions to create. + QOSMarking qos = 4; // DSCP marking to be used. // Mode of the subscription. enum Mode { - STREAM = 0; // Values streamed by the target (Sec. 3.5.1.5.2). - ONCE = 1; // Values sent once-off by the target (Sec. 3.5.1.5.1). - POLL = 2; // Values sent in response to a poll request (Sec. 3.5.1.5.3). + STREAM = 0; // Values streamed by the target (Sec. 3.5.1.5.2). + ONCE = 1; // Values sent once-off by the target (Sec. 3.5.1.5.1). + POLL = 2; // Values sent in response to a poll request (Sec. 3.5.1.5.3). } Mode mode = 5; // Whether elements of the schema that are marked as eligible for aggregation @@ -294,9 +297,9 @@ message SubscriptionList { // should trigger updates to be sent. // Reference: gNMI Specification Section 3.5.1.3 message Subscription { - Path path = 1; // The data tree path. - SubscriptionMode mode = 2; // Subscription mode to be used. - uint64 sample_interval = 3; // ns between samples in SAMPLE mode. + Path path = 1; // The data tree path. + SubscriptionMode mode = 2; // Subscription mode to be used. + uint64 sample_interval = 3; // ns between samples in SAMPLE mode. // Indicates whether values that have not changed should be sent in a SAMPLE // subscription. bool suppress_redundant = 4; @@ -311,8 +314,8 @@ message Subscription { // Reference: gNMI Specification Section 3.5.1.3 enum SubscriptionMode { TARGET_DEFINED = 0; // The target selects the relevant mode for each element. - ON_CHANGE = 1; // The target sends an update on element value change. - SAMPLE = 2; // The target samples values according to the interval. + ON_CHANGE = 1; // The target sends an update on element value change. + SAMPLE = 2; // The target samples values according to the interval. } // QOSMarking specifies the DSCP value to be set on transmitted telemetry @@ -330,10 +333,10 @@ message QOSMarking { // a single SetRequest are considered to be a transaction. // Reference: gNMI Specification Section 3.4.1 message SetRequest { - Path prefix = 1; // Prefix used for paths in the message. - repeated Path delete = 2; // Paths to be deleted from the data tree. - repeated Update replace = 3; // Updates specifying elements to be replaced. - repeated Update update = 4; // Updates specifying elements to updated. + Path prefix = 1; // Prefix used for paths in the message. + repeated Path delete = 2; // Paths to be deleted from the data tree. + repeated Update replace = 3; // Updates specifying elements to be replaced. + repeated Update update = 4; // Updates specifying elements to updated. // Extension messages associated with the SetRequest. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 5; @@ -343,16 +346,17 @@ message SetRequest { // client. It reports the result of the modifications to the data tree that were // specified by the client. Errors for this RPC should be reported using the // https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto -// message in the RPC return. The gnmi.Error message can be used to add additional -// details where required. -// Reference: gNMI Specification Section 3.4.2 +// message in the RPC return. The gnmi.Error message can be used to add +// additional details where required. Reference: gNMI Specification +// Section 3.4.2 message SetResponse { - Path prefix = 1; // Prefix used for paths. + Path prefix = 1; // Prefix used for paths. // A set of responses specifying the result of the operations specified in // the SetRequest. repeated UpdateResult response = 2; - Error message = 3 [deprecated=true]; // The overall status of the transaction. - int64 timestamp = 4; // Timestamp of transaction (ns since epoch). + Error message = 3 + [deprecated = true]; // The overall status of the transaction. + int64 timestamp = 4; // Timestamp of transaction (ns since epoch). // Extension messages associated with the SetResponse. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 5; @@ -365,18 +369,18 @@ message UpdateResult { // The operation that was associated with the Path specified. enum Operation { INVALID = 0; - DELETE = 1; // The result relates to a delete of Path. - REPLACE = 2; // The result relates to a replace of Path. - UPDATE = 3; // The result relates to an update of Path. + DELETE = 1; // The result relates to a delete of Path. + REPLACE = 2; // The result relates to a replace of Path. + UPDATE = 3; // The result relates to an update of Path. } // Deprecated timestamp for the UpdateResult, this field has been // replaced by the timestamp within the SetResponse message, since // all mutations effected by a set should be applied as a single // transaction. - int64 timestamp = 1 [deprecated=true]; - Path path = 2; // Path associated with the update. - Error message = 3 [deprecated=true]; // Status of the update operation. - Operation op = 4; // Update operation type. + int64 timestamp = 1 [deprecated = true]; + Path path = 2; // Path associated with the update. + Error message = 3 [deprecated = true]; // Status of the update operation. + Operation op = 4; // Update operation type. } // GetRequest is sent when a client initiates a Get RPC. It is used to specify @@ -386,21 +390,21 @@ message UpdateResult { // must use all schema models that it has. // Reference: gNMI Specification Section 3.3.1 message GetRequest { - Path prefix = 1; // Prefix used for paths. - repeated Path path = 2; // Paths requested by the client. + Path prefix = 1; // Prefix used for paths. + repeated Path path = 2; // Paths requested by the client. // Type of elements within the data tree. enum DataType { - ALL = 0; // All data elements. - CONFIG = 1; // Config (rw) only elements. - STATE = 2; // State (ro) only elements. + ALL = 0; // All data elements. + CONFIG = 1; // Config (rw) only elements. + STATE = 2; // State (ro) only elements. // Data elements marked in the schema as operational. This refers to data // elements whose value relates to the state of processes or interactions // running on the device. OPERATIONAL = 3; } - DataType type = 3; // The type of data being requested. - Encoding encoding = 5; // Encoding to be used. - repeated ModelData use_models = 6; // The schema models to be used. + DataType type = 3; // The type of data being requested. + Encoding encoding = 5; // Encoding to be used. + repeated ModelData use_models = 6; // The schema models to be used. // Extension messages associated with the GetRequest. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 7; @@ -411,8 +415,8 @@ message GetRequest { // by the client in the GetRequest. // Reference: gNMI Specification Section 3.3.2 message GetResponse { - repeated Notification notification = 1; // Data values. - Error error = 2 [deprecated=true]; // Errors that occurred in the Get. + repeated Notification notification = 1; // Data values. + Error error = 2 [deprecated = true]; // Errors that occurred in the Get. // Extension messages associated with the GetResponse. See the // gNMI extension specification for further definition. repeated gnmi_ext.Extension extension = 3; @@ -445,7 +449,7 @@ message CapabilityResponse { // the set of models from which data tree elements should be reported. // Reference: gNMI Specification Section 3.2.3 message ModelData { - string name = 1; // Name of the model. - string organization = 2; // Organization publishing the model. - string version = 3; // Semantic version of the model. + string name = 1; // Name of the model. + string organization = 2; // Organization publishing the model. + string version = 3; // Semantic version of the model. } diff --git a/proto/gnmi/gnmi_pb2.py b/proto/gnmi/gnmi_pb2.py index f0f4d3a..8d165c9 100644 --- a/proto/gnmi/gnmi_pb2.py +++ b/proto/gnmi/gnmi_pb2.py @@ -18,7 +18,7 @@ from github.com.openconfig.gnmi.proto.gnmi_ext import gnmi_ext_pb2 as github_dot_com_dot_openconfig_dot_gnmi_dot_proto_dot_gnmi__ext_dot_gnmi__ext__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15proto/gnmi/gnmi.proto\x12\x04gnmi\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\x38github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto\"\x94\x01\n\x0cNotification\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\x1a\n\x06prefix\x18\x02 \x01(\x0b\x32\n.gnmi.Path\x12\x1c\n\x06update\x18\x04 \x03(\x0b\x32\x0c.gnmi.Update\x12\x1a\n\x06\x64\x65lete\x18\x05 \x03(\x0b\x32\n.gnmi.Path\x12\x0e\n\x06\x61tomic\x18\x06 \x01(\x08J\x04\x08\x03\x10\x04R\x05\x61lias\"u\n\x06Update\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x1e\n\x05value\x18\x02 \x01(\x0b\x32\x0b.gnmi.ValueB\x02\x18\x01\x12\x1d\n\x03val\x18\x03 \x01(\x0b\x32\x10.gnmi.TypedValue\x12\x12\n\nduplicates\x18\x04 \x01(\r\"\x83\x03\n\nTypedValue\x12\x14\n\nstring_val\x18\x01 \x01(\tH\x00\x12\x11\n\x07int_val\x18\x02 \x01(\x03H\x00\x12\x12\n\x08uint_val\x18\x03 \x01(\x04H\x00\x12\x12\n\x08\x62ool_val\x18\x04 \x01(\x08H\x00\x12\x13\n\tbytes_val\x18\x05 \x01(\x0cH\x00\x12\x17\n\tfloat_val\x18\x06 \x01(\x02\x42\x02\x18\x01H\x00\x12\x14\n\ndouble_val\x18\x0e \x01(\x01H\x00\x12*\n\x0b\x64\x65\x63imal_val\x18\x07 \x01(\x0b\x32\x0f.gnmi.Decimal64B\x02\x18\x01H\x00\x12)\n\x0cleaflist_val\x18\x08 \x01(\x0b\x32\x11.gnmi.ScalarArrayH\x00\x12\'\n\x07\x61ny_val\x18\t \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x12\x12\n\x08json_val\x18\n \x01(\x0cH\x00\x12\x17\n\rjson_ietf_val\x18\x0b \x01(\x0cH\x00\x12\x13\n\tascii_val\x18\x0c \x01(\tH\x00\x12\x15\n\x0bproto_bytes\x18\r \x01(\x0cH\x00\x42\x07\n\x05value\"Y\n\x04Path\x12\x13\n\x07\x65lement\x18\x01 \x03(\tB\x02\x18\x01\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x1c\n\x04\x65lem\x18\x03 \x03(\x0b\x32\x0e.gnmi.PathElem\x12\x0e\n\x06target\x18\x04 \x01(\t\"j\n\x08PathElem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12$\n\x03key\x18\x02 \x03(\x0b\x32\x17.gnmi.PathElem.KeyEntry\x1a*\n\x08KeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"8\n\x05Value\x12\r\n\x05value\x18\x01 \x01(\x0c\x12\x1c\n\x04type\x18\x02 \x01(\x0e\x32\x0e.gnmi.Encoding:\x02\x18\x01\"N\n\x05\x45rror\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\"\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x14.google.protobuf.Any:\x02\x18\x01\"2\n\tDecimal64\x12\x0e\n\x06\x64igits\x18\x01 \x01(\x03\x12\x11\n\tprecision\x18\x02 \x01(\r:\x02\x18\x01\"0\n\x0bScalarArray\x12!\n\x07\x65lement\x18\x01 \x03(\x0b\x32\x10.gnmi.TypedValue\"\x9d\x01\n\x10SubscribeRequest\x12+\n\tsubscribe\x18\x01 \x01(\x0b\x32\x16.gnmi.SubscriptionListH\x00\x12\x1a\n\x04poll\x18\x03 \x01(\x0b\x32\n.gnmi.PollH\x00\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.ExtensionB\t\n\x07requestJ\x04\x08\x04\x10\x05R\x07\x61liases\"\x06\n\x04Poll\"\xa8\x01\n\x11SubscribeResponse\x12$\n\x06update\x18\x01 \x01(\x0b\x32\x12.gnmi.NotificationH\x00\x12\x17\n\rsync_response\x18\x03 \x01(\x08H\x00\x12 \n\x05\x65rror\x18\x04 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01H\x00\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.ExtensionB\n\n\x08response\"\xd5\x02\n\x10SubscriptionList\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12(\n\x0csubscription\x18\x02 \x03(\x0b\x32\x12.gnmi.Subscription\x12\x1d\n\x03qos\x18\x04 \x01(\x0b\x32\x10.gnmi.QOSMarking\x12)\n\x04mode\x18\x05 \x01(\x0e\x32\x1b.gnmi.SubscriptionList.Mode\x12\x19\n\x11\x61llow_aggregation\x18\x06 \x01(\x08\x12#\n\nuse_models\x18\x07 \x03(\x0b\x32\x0f.gnmi.ModelData\x12 \n\x08\x65ncoding\x18\x08 \x01(\x0e\x32\x0e.gnmi.Encoding\x12\x14\n\x0cupdates_only\x18\t \x01(\x08\"&\n\x04Mode\x12\n\n\x06STREAM\x10\x00\x12\x08\n\x04ONCE\x10\x01\x12\x08\n\x04POLL\x10\x02J\x04\x08\x03\x10\x04R\x0buse_aliases\"\x9f\x01\n\x0cSubscription\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12$\n\x04mode\x18\x02 \x01(\x0e\x32\x16.gnmi.SubscriptionMode\x12\x17\n\x0fsample_interval\x18\x03 \x01(\x04\x12\x1a\n\x12suppress_redundant\x18\x04 \x01(\x08\x12\x1a\n\x12heartbeat_interval\x18\x05 \x01(\x04\"\x1d\n\nQOSMarking\x12\x0f\n\x07marking\x18\x01 \x01(\r\"\xa9\x01\n\nSetRequest\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x1a\n\x06\x64\x65lete\x18\x02 \x03(\x0b\x32\n.gnmi.Path\x12\x1d\n\x07replace\x18\x03 \x03(\x0b\x32\x0c.gnmi.Update\x12\x1c\n\x06update\x18\x04 \x03(\x0b\x32\x0c.gnmi.Update\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xac\x01\n\x0bSetResponse\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12$\n\x08response\x18\x02 \x03(\x0b\x32\x12.gnmi.UpdateResult\x12 \n\x07message\x18\x03 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xca\x01\n\x0cUpdateResult\x12\x15\n\ttimestamp\x18\x01 \x01(\x03\x42\x02\x18\x01\x12\x18\n\x04path\x18\x02 \x01(\x0b\x32\n.gnmi.Path\x12 \n\x07message\x18\x03 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12(\n\x02op\x18\x04 \x01(\x0e\x32\x1c.gnmi.UpdateResult.Operation\"=\n\tOperation\x12\x0b\n\x07INVALID\x10\x00\x12\n\n\x06\x44\x45LETE\x10\x01\x12\x0b\n\x07REPLACE\x10\x02\x12\n\n\x06UPDATE\x10\x03\"\x97\x02\n\nGetRequest\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x18\n\x04path\x18\x02 \x03(\x0b\x32\n.gnmi.Path\x12\'\n\x04type\x18\x03 \x01(\x0e\x32\x19.gnmi.GetRequest.DataType\x12 \n\x08\x65ncoding\x18\x05 \x01(\x0e\x32\x0e.gnmi.Encoding\x12#\n\nuse_models\x18\x06 \x03(\x0b\x32\x0f.gnmi.ModelData\x12&\n\textension\x18\x07 \x03(\x0b\x32\x13.gnmi_ext.Extension\";\n\x08\x44\x61taType\x12\x07\n\x03\x41LL\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\t\n\x05STATE\x10\x02\x12\x0f\n\x0bOPERATIONAL\x10\x03\"\x7f\n\x0bGetResponse\x12(\n\x0cnotification\x18\x01 \x03(\x0b\x32\x12.gnmi.Notification\x12\x1e\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12&\n\textension\x18\x03 \x03(\x0b\x32\x13.gnmi_ext.Extension\";\n\x11\x43\x61pabilityRequest\x12&\n\textension\x18\x01 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xaa\x01\n\x12\x43\x61pabilityResponse\x12)\n\x10supported_models\x18\x01 \x03(\x0b\x32\x0f.gnmi.ModelData\x12+\n\x13supported_encodings\x18\x02 \x03(\x0e\x32\x0e.gnmi.Encoding\x12\x14\n\x0cgNMI_version\x18\x03 \x01(\t\x12&\n\textension\x18\x04 \x03(\x0b\x32\x13.gnmi_ext.Extension\"@\n\tModelData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t*D\n\x08\x45ncoding\x12\x08\n\x04JSON\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\t\n\x05PROTO\x10\x02\x12\t\n\x05\x41SCII\x10\x03\x12\r\n\tJSON_IETF\x10\x04*A\n\x10SubscriptionMode\x12\x12\n\x0eTARGET_DEFINED\x10\x00\x12\r\n\tON_CHANGE\x10\x01\x12\n\n\x06SAMPLE\x10\x02\x32\xe3\x01\n\x04gNMI\x12\x41\n\x0c\x43\x61pabilities\x12\x17.gnmi.CapabilityRequest\x1a\x18.gnmi.CapabilityResponse\x12*\n\x03Get\x12\x10.gnmi.GetRequest\x1a\x11.gnmi.GetResponse\x12*\n\x03Set\x12\x10.gnmi.SetRequest\x1a\x11.gnmi.SetResponse\x12@\n\tSubscribe\x12\x16.gnmi.SubscribeRequest\x1a\x17.gnmi.SubscribeResponse(\x01\x30\x01:3\n\x0cgnmi_service\x12\x1c.google.protobuf.FileOptions\x18\xe9\x07 \x01(\tBS\n\x15\x63om.github.gnmi.protoB\tGnmiProtoP\x01Z%github.com/openconfig/gnmi/proto/gnmi\xca>\x05\x30.8.0b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15proto/gnmi/gnmi.proto\x12\x04gnmi\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\x38github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto\"\x94\x01\n\x0cNotification\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\x1a\n\x06prefix\x18\x02 \x01(\x0b\x32\n.gnmi.Path\x12\x1c\n\x06update\x18\x04 \x03(\x0b\x32\x0c.gnmi.Update\x12\x1a\n\x06\x64\x65lete\x18\x05 \x03(\x0b\x32\n.gnmi.Path\x12\x0e\n\x06\x61tomic\x18\x06 \x01(\x08J\x04\x08\x03\x10\x04R\x05\x61lias\"u\n\x06Update\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x1e\n\x05value\x18\x02 \x01(\x0b\x32\x0b.gnmi.ValueB\x02\x18\x01\x12\x1d\n\x03val\x18\x03 \x01(\x0b\x32\x10.gnmi.TypedValue\x12\x12\n\nduplicates\x18\x04 \x01(\r\"\x83\x03\n\nTypedValue\x12\x14\n\nstring_val\x18\x01 \x01(\tH\x00\x12\x11\n\x07int_val\x18\x02 \x01(\x03H\x00\x12\x12\n\x08uint_val\x18\x03 \x01(\x04H\x00\x12\x12\n\x08\x62ool_val\x18\x04 \x01(\x08H\x00\x12\x13\n\tbytes_val\x18\x05 \x01(\x0cH\x00\x12\x17\n\tfloat_val\x18\x06 \x01(\x02\x42\x02\x18\x01H\x00\x12\x14\n\ndouble_val\x18\x0e \x01(\x01H\x00\x12*\n\x0b\x64\x65\x63imal_val\x18\x07 \x01(\x0b\x32\x0f.gnmi.Decimal64B\x02\x18\x01H\x00\x12)\n\x0cleaflist_val\x18\x08 \x01(\x0b\x32\x11.gnmi.ScalarArrayH\x00\x12\'\n\x07\x61ny_val\x18\t \x01(\x0b\x32\x14.google.protobuf.AnyH\x00\x12\x12\n\x08json_val\x18\n \x01(\x0cH\x00\x12\x17\n\rjson_ietf_val\x18\x0b \x01(\x0cH\x00\x12\x13\n\tascii_val\x18\x0c \x01(\tH\x00\x12\x15\n\x0bproto_bytes\x18\r \x01(\x0cH\x00\x42\x07\n\x05value\"Y\n\x04Path\x12\x13\n\x07\x65lement\x18\x01 \x03(\tB\x02\x18\x01\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x1c\n\x04\x65lem\x18\x03 \x03(\x0b\x32\x0e.gnmi.PathElem\x12\x0e\n\x06target\x18\x04 \x01(\t\"j\n\x08PathElem\x12\x0c\n\x04name\x18\x01 \x01(\t\x12$\n\x03key\x18\x02 \x03(\x0b\x32\x17.gnmi.PathElem.KeyEntry\x1a*\n\x08KeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"8\n\x05Value\x12\r\n\x05value\x18\x01 \x01(\x0c\x12\x1c\n\x04type\x18\x02 \x01(\x0e\x32\x0e.gnmi.Encoding:\x02\x18\x01\"N\n\x05\x45rror\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\"\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x14.google.protobuf.Any:\x02\x18\x01\"2\n\tDecimal64\x12\x0e\n\x06\x64igits\x18\x01 \x01(\x03\x12\x11\n\tprecision\x18\x02 \x01(\r:\x02\x18\x01\"0\n\x0bScalarArray\x12!\n\x07\x65lement\x18\x01 \x03(\x0b\x32\x10.gnmi.TypedValue\"\x9d\x01\n\x10SubscribeRequest\x12+\n\tsubscribe\x18\x01 \x01(\x0b\x32\x16.gnmi.SubscriptionListH\x00\x12\x1a\n\x04poll\x18\x03 \x01(\x0b\x32\n.gnmi.PollH\x00\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.ExtensionB\t\n\x07requestJ\x04\x08\x04\x10\x05R\x07\x61liases\"\x06\n\x04Poll\"\xa8\x01\n\x11SubscribeResponse\x12$\n\x06update\x18\x01 \x01(\x0b\x32\x12.gnmi.NotificationH\x00\x12\x17\n\rsync_response\x18\x03 \x01(\x08H\x00\x12 \n\x05\x65rror\x18\x04 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01H\x00\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.ExtensionB\n\n\x08response\"\xd5\x02\n\x10SubscriptionList\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12(\n\x0csubscription\x18\x02 \x03(\x0b\x32\x12.gnmi.Subscription\x12\x1d\n\x03qos\x18\x04 \x01(\x0b\x32\x10.gnmi.QOSMarking\x12)\n\x04mode\x18\x05 \x01(\x0e\x32\x1b.gnmi.SubscriptionList.Mode\x12\x19\n\x11\x61llow_aggregation\x18\x06 \x01(\x08\x12#\n\nuse_models\x18\x07 \x03(\x0b\x32\x0f.gnmi.ModelData\x12 \n\x08\x65ncoding\x18\x08 \x01(\x0e\x32\x0e.gnmi.Encoding\x12\x14\n\x0cupdates_only\x18\t \x01(\x08\"&\n\x04Mode\x12\n\n\x06STREAM\x10\x00\x12\x08\n\x04ONCE\x10\x01\x12\x08\n\x04POLL\x10\x02J\x04\x08\x03\x10\x04R\x0buse_aliases\"\x9f\x01\n\x0cSubscription\x12\x18\n\x04path\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12$\n\x04mode\x18\x02 \x01(\x0e\x32\x16.gnmi.SubscriptionMode\x12\x17\n\x0fsample_interval\x18\x03 \x01(\x04\x12\x1a\n\x12suppress_redundant\x18\x04 \x01(\x08\x12\x1a\n\x12heartbeat_interval\x18\x05 \x01(\x04\"\x1d\n\nQOSMarking\x12\x0f\n\x07marking\x18\x01 \x01(\r\"\xa9\x01\n\nSetRequest\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x1a\n\x06\x64\x65lete\x18\x02 \x03(\x0b\x32\n.gnmi.Path\x12\x1d\n\x07replace\x18\x03 \x03(\x0b\x32\x0c.gnmi.Update\x12\x1c\n\x06update\x18\x04 \x03(\x0b\x32\x0c.gnmi.Update\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xac\x01\n\x0bSetResponse\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12$\n\x08response\x18\x02 \x03(\x0b\x32\x12.gnmi.UpdateResult\x12 \n\x07message\x18\x03 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12&\n\textension\x18\x05 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xca\x01\n\x0cUpdateResult\x12\x15\n\ttimestamp\x18\x01 \x01(\x03\x42\x02\x18\x01\x12\x18\n\x04path\x18\x02 \x01(\x0b\x32\n.gnmi.Path\x12 \n\x07message\x18\x03 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12(\n\x02op\x18\x04 \x01(\x0e\x32\x1c.gnmi.UpdateResult.Operation\"=\n\tOperation\x12\x0b\n\x07INVALID\x10\x00\x12\n\n\x06\x44\x45LETE\x10\x01\x12\x0b\n\x07REPLACE\x10\x02\x12\n\n\x06UPDATE\x10\x03\"\x97\x02\n\nGetRequest\x12\x1a\n\x06prefix\x18\x01 \x01(\x0b\x32\n.gnmi.Path\x12\x18\n\x04path\x18\x02 \x03(\x0b\x32\n.gnmi.Path\x12\'\n\x04type\x18\x03 \x01(\x0e\x32\x19.gnmi.GetRequest.DataType\x12 \n\x08\x65ncoding\x18\x05 \x01(\x0e\x32\x0e.gnmi.Encoding\x12#\n\nuse_models\x18\x06 \x03(\x0b\x32\x0f.gnmi.ModelData\x12&\n\textension\x18\x07 \x03(\x0b\x32\x13.gnmi_ext.Extension\";\n\x08\x44\x61taType\x12\x07\n\x03\x41LL\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\t\n\x05STATE\x10\x02\x12\x0f\n\x0bOPERATIONAL\x10\x03\"\x7f\n\x0bGetResponse\x12(\n\x0cnotification\x18\x01 \x03(\x0b\x32\x12.gnmi.Notification\x12\x1e\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x0b.gnmi.ErrorB\x02\x18\x01\x12&\n\textension\x18\x03 \x03(\x0b\x32\x13.gnmi_ext.Extension\";\n\x11\x43\x61pabilityRequest\x12&\n\textension\x18\x01 \x03(\x0b\x32\x13.gnmi_ext.Extension\"\xaa\x01\n\x12\x43\x61pabilityResponse\x12)\n\x10supported_models\x18\x01 \x03(\x0b\x32\x0f.gnmi.ModelData\x12+\n\x13supported_encodings\x18\x02 \x03(\x0e\x32\x0e.gnmi.Encoding\x12\x14\n\x0cgNMI_version\x18\x03 \x01(\t\x12&\n\textension\x18\x04 \x03(\x0b\x32\x13.gnmi_ext.Extension\"@\n\tModelData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0corganization\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t*D\n\x08\x45ncoding\x12\x08\n\x04JSON\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\t\n\x05PROTO\x10\x02\x12\t\n\x05\x41SCII\x10\x03\x12\r\n\tJSON_IETF\x10\x04*A\n\x10SubscriptionMode\x12\x12\n\x0eTARGET_DEFINED\x10\x00\x12\r\n\tON_CHANGE\x10\x01\x12\n\n\x06SAMPLE\x10\x02\x32\xe3\x01\n\x04gNMI\x12\x41\n\x0c\x43\x61pabilities\x12\x17.gnmi.CapabilityRequest\x1a\x18.gnmi.CapabilityResponse\x12*\n\x03Get\x12\x10.gnmi.GetRequest\x1a\x11.gnmi.GetResponse\x12*\n\x03Set\x12\x10.gnmi.SetRequest\x1a\x11.gnmi.SetResponse\x12@\n\tSubscribe\x12\x16.gnmi.SubscribeRequest\x1a\x17.gnmi.SubscribeResponse(\x01\x30\x01:3\n\x0cgnmi_service\x12\x1c.google.protobuf.FileOptions\x18\xe9\x07 \x01(\tBS\n\x15\x63om.github.gnmi.protoB\tGnmiProtoP\x01Z%github.com/openconfig/gnmi/proto/gnmi\xca>\x05\x30.9.0b\x06proto3') _ENCODING = DESCRIPTOR.enum_types_by_name['Encoding'] Encoding = enum_type_wrapper.EnumTypeWrapper(_ENCODING) @@ -237,7 +237,7 @@ google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(gnmi_service) DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'\n\025com.github.gnmi.protoB\tGnmiProtoP\001Z%github.com/openconfig/gnmi/proto/gnmi\312>\0050.8.0' + DESCRIPTOR._serialized_options = b'\n\025com.github.gnmi.protoB\tGnmiProtoP\001Z%github.com/openconfig/gnmi/proto/gnmi\312>\0050.9.0' _UPDATE.fields_by_name['value']._options = None _UPDATE.fields_by_name['value']._serialized_options = b'\030\001' _TYPEDVALUE.fields_by_name['float_val']._options = None