<commit_before>syntax = "proto3";

import "google/protobuf/any.proto";

// Package openconfig defines the gRPC service for getting and setting the
// OpenConfig configuration and state of a network device.
//
// This package and its contents have not been ratified by OpenConfig.  It is
// a working proposal by Google.
package openconfig;

service OpenConfig {
  // Get requests a single snapshot of specified data.  A Get request may
  // contain a hint that the request will be repeated (i.e., polling).
  rpc Get(GetRequest) returns (GetResponse);

  // GetModels returns the current YANG models supported by the device.
  rpc GetModels(GetModelsRequest) returns (GetModelsResponse);

  // Set sets the paths contained in the SetRequest to the values If a path does
  // not exist, or is read-only the SetResponse will return an error.  All paths
  // in the SetRequest must be valid or the entire request must be rejected.  If
  // a path specifies a node, rather than the leaf, then the value must be the
  // values of the node's children encoded in JSON.  Binary data in the tree
  // must be base64 encoded.
  rpc Set(stream SetRequest) returns (stream SetResponse);

  // Subscribe subscribes for streaming updates.  Streaming updates are provided
  // as a series of Notifications, each of which update a portion of the tree.
  // The target must send the current values of all subscribed paths at the
  // start of the stream, followed by a sync_response of 0.
  //
  // A Subscription operates in one of three modes.
  //
  // Streaming:  This is the default mode.  The target sends continual updates
  // of each value as specified by each subscription's sample_interval.  The
  // client may request the target to resend the current value of a set of paths
  // by sending a SyncRequest.
  //
  // Once: This mode is specified by setting once to true in the
  // SubscriptionRequest.  The target must close the stream after sending the
  // sync_response of 0.  The target should only send each value once.
  //
  // Poll: This mode is the equivalent of periodic Once requests but sent over a
  // single stream.  This is more efficient than sending multiple Once requests
  // as the target only need parse the subscription once.  It also has an
  // advantage over Streaming as the client is in control of when the target
  // should send data again.
  //
  // To poll, the client sends a SubscriptionRequest with poll_interval set to
  // exepected length of time, in nanoseconds, until the next poll.  The target
  // respods by sending each subscribed value once followed by a sync_resposne
  // of 0.  For each following poll, the client sends a SubscriptionRequest on
  // the same stream with only poll_interval set with the next expected
  // interval.  The target again responses with each subscribed value once
  // followed by a sync_response of 0.
  rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeResponse);
}

// A Notification is a list of updates to apply.  Deletes are a list of paths to
// delete as long as their data is older than timestamp.  Deleting nodes deletes
// all values below the node that are older than timestamp.  Deletes are
// performed after updates are applied.  Delete paths are created by
// concatenating the prefix, if present, with the individual paths.
//
// Update paths are created by concatenating the prefix, if present, with the
// paths contained in the Updates.
//
// It is valid to have a path be both in an update and match a delete.  The
// deletion will only delete values that are older than this update.
//
// Each notification should contain at most a single update for a given path.
// If a nonconforming implementation does send multiple updates for a given path
// in a single notification, all but the final update should be ignored.
//
// The prefix should normally be the longest common prefix to all the individual
// update and delete path.  This reduces the repetition of the common prefix in
// each update and/or delete.  The individual updates and deletes also are a
// Path (repeated list of elements), allowing a notification such as:
//
//   prefix: /a/b/c
//   update: {
//     path: d
//     value: x
//   }
//   update: {
//     path: e/f
//     value: y
//   }
//   update: {
//     path: e/g
//     value: z
//   }
//
// The prefix may begin with an alias.  An alias is a Path with 1 or more
// elements, which maps to another Path.  Aliases may be defined by either the
// target or the client.  Target defined aliases are limited to a single
// element.  Aliases are client specific (though a target may define the same
// alias for multiple clients).
//
// The target defines an alias by sending a Notification that has alias set and
// a non-empty prefix. When alias is set, a Notification need not provide
// updates or deletes.  If the alias was previously defined, it is over ridden
// with the new definition.  Once defined, the target may send the value of
// alias as the first element of a prefix.  A target must not send target
// defined aliases to clients that do not specify the use_aliases option in the
// initial SubscriptionList message.  A target does not need to define aliases
// even if the client does specify the use_aliases option in the initial
// SubscriptionLlist message.
//
// Clients define aliases by sending a SubscriptionRequest with aliases set.
//
// A target should use a define alias when possible, but is not required to.  A
// target may ignore client defined aliases.
//
// Clients should not define aliases that valid paths in the data tree.  The
// target must not define aliases that valid paths in the dat tree.
//
// If a target sends a notification with alias set, but not prefix, then it is
// indicating it will no longer use this alias.  The client may delete this
// alias from its list of aliases.  A target may not delete an alias defined by
// the client.  It is implementation dependent on what happens if the client
// defines an alias that is also defined by the target.
//
// Aliases must not be used in UDP packets.
//
// If a client sets the use_aliases option, or defines aliases, in the initial
// SubscriptionList message, then it must always check the initial elements of a
// prefix against the list of known aliases, expanding the prefix as needed.
// Aliases must always be defined as fully expanded prefixes.  Only single alias
// lookup is needed per Notification.
//
// Target defined aliases may be any unique string.  A target may choose to use
// a unique prefix for aliases to make them visually distinct.  For example, a
// target might construct all aliases as an @ character followed by a decimal or
// hexadecimal number (perhaps a hashed address in memory).
//
// Example:
//
// Define @42 as an alias:
//
//   timestamp: 1439416376123456789
//   prefix: "this_is"
//   prefix: "a_long"
//   prefix: "prefix"
//   alias: "@42
//
// Use @42 as an alias to set /this_is/a_long/prefix/Ethernet0/0/1/in-octets to
// 17:
//
//   timestamp: 1439416376456456456
//   prefix: "@42"
//   prefix: "Ethernet0/0/1"
//   update: {
//     path: {
//       element: "in-octets"
//     }
//     value: 17
//   }
//
// Delete the alias @42:
//
//   timestamp: 1439416376987654321
//   alias: @42
message Notification {
  int64 timestamp = 1;
  Path prefix = 2;
  string alias = 3;
  repeated Update update = 4;
  repeated Path delete = 5;
}

// An Update maps a path to a value.
//
// In a Notification, an Update represents a new or updated value for path.  The
// absolute path name is the concatenation of the Notification prefix and the
// Update path.  Updates are only sent by the target.  Path must always specify
// a leaf node.  Value should be a scalar value (e.g., if Value is JSON encoded
// then the value 123 is acceptable, but {"x":123} is not).
//
// In a SetRequest, an Update contains a path to a read-write node and an
// optional value.  The absolute path name is the concatenation of the
// SetRequest prefix and the Update path The path may reference either a
// directory or leaf node.  If value is not present then path, and all its
// subelements, should be removed.  If value set and path references a directory
// node, the value is the JSON encoded tree of values below that node,
// otherwise, if the value is a scalar and may be encoded in JSON are as raw
// BYTES.  the value
//
// For an example of updating a directory node, consider a tree that has the
// following values:
//
//   /a/b/c: 1
//   /a/b/d: 2
//   /a/b/e: 3
//
// And an Update of
//
//   Path: /a/b
//   Value: "{c: 4, f: 5}"
//
// The result is that /a/b/d and /a/b/e are removed, /a/b/c now has the value of
// 4, and /a/b/f is added with the value of 5.
message Update {
   Path path = 1;
   Value value = 2;
}

// A Path represents an open config path as a list of strings, one element
// per string.
message Path {
  repeated string element = 1;
}

// A Value is either raw data or a JSON encoded value.  An enumerated value is
// of type JSON, with the numeric value in the value field and the name of the
// enumerated value in the name field.
message Value {
  bytes value = 1;
  Type type = 2;
  string name = 3;
}

// A Type describes what format a Value's data is encoded in.
enum Type {
  JSON = 0;
  BYTES = 1;
}

// GetModelsRequest contains a list of models to return.  If no queries are
// specified, all currently support models will be returned.  ModelReturnType
// specifies the format of the model to return.  By default, only summaries will
// be returned.
message GetModelsRequest {
  // Type selects to return only the summary model information or
  // the full YANG model as bytes.  The caller is responsible for extracting the
  // YANG model from the bytes.
  enum Type {
    SUMMARY = 0; // Request only name, namespace, version information.
    DETAIL = 1;  // Request the YANG model as well has summary information.
  }
  Type request_type = 1;
  ModelQuery query = 2;
}

// ModelQuery contains a name and/or namespace regex pattern to match against
// supported models on the system.
message ModelQuery {
  string name = 1;      // re2 pattern match of the model name.
  string namespace = 2; // re2 pattern match of the model namespace.
  string version = 3;   // re2 pattern match of the model version.
}

// GetModelsResponse returns a list of models supported by the system.
message GetModelsResponse {
  // List of models supported by the system.
  repeated ModelData models = 1;
}

// ModelData contains the summary information for the model as well as the
// actual model data if requested.
message ModelData {
  string name = 1;      // name of the model.
  string namespace = 2; // namespace of the model.
  string version = 3;   // version supported.
  bytes data = 4;       // byte data of the YANG text file.
}

// A GetRequest requests all the values identified by path be returns in a
// single GetResponse message.
//
// If cache_interval is provided and is non-zero number of nanoseconds, it is
// a hint of when this get request will be repeated in the future.
message GetRequest {
  Path prefix = 1;          // If set, each path is realitve to prefix
  repeated Path path = 2;   // List of paths to return information for
  // Type defines the mode that Get should use (GET_DATA_COMMANDS in the
  // YANG schema).  Only ALL is required by all implementation.
  enum Type {
    ALL         = 0; // Return all data
    CONFIG      = 1; // Only return values in Config containers
    STATE       = 2; // Only return values in State containers
    OPERATIONAL = 3; // Only values in State containers not modeled in Config
  }
  Type type = 3;         // Limit what type of values are returned.
  int64 cache_interval = 4;
}

message GetResponse {
  repeated Notification notification = 1;
}

// A SetRequest contains an optional prefix, a list of zero or more Paths to
// delete, a list of zero or more paths to replace, and a list of zero of more
// paths to update.  Deletes should appear to happen first, followed by
// replacements, followed by updates.
//
// If the path lists a node, rather than leaf, the value is presented in JSON.
// When included in replace, it is as if the path was first deleted.  When
// included in update, the value aguments the existing value, if any.
//
// The target must either apply all the deletes, replacements, and updates or
// return an error.  The deletes, replacements, and updates should appear to be
// atomically applied.
message SetRequest {
  Path prefix = 1;
  repeated Path delete = 2;
  repeated Update replace = 3;
  repeated Update update = 4;
}

// A SetResponse contains responses to a SetRequest.  The optional prefix is
// applied to all paths in response.  Each path provided by a SetRequest needs a
// response, but there need not be a 1:1 correspondence between SetRequests and
// SetResponses (e.g., the target may issue a single response to multiple
// requests, or multiple responses to a single request).
message SetResponse {
  Path prefix = 1;
  repeated UpdateResponse response = 2;
}

// An UpdateResponse contains the response for a single path Update.
message UpdateResponse {
  // The timestamp is the time, in nanoseconds since the epoch, that a Set was
  // accepted (i.e., the request was valid).  It does not imply the value was
  // actually propagated to an underlying datastore.
  int64 timestamp = 1;
  Path path = 2;       // path provided in SetRequest.
  Error error = 3;     // optional error, if set, timestamp is optional
}

// An Error contains information about why a particular request failed.
//
// The canonical error codes are defined for each language.
//
//   Go:   import "google.golang.org/grpc/codes"
//   C++:  #include <grpc++/status_code_enum.h>
//   Java: import static io.grpc.Status.Code;
//   C:    #include <grpc/status.h>
//   C#:   using Grpc.Core;
message Error {
  uint32 code = 1;                // Canonical grpc error code
  string message = 2;             // Human readable error
  google.protobuf.Any data = 3;   // optional additional information
}

// A SubscribeRequest is either a subscription request, a change to the
// heartbeat rate, or a request for resynchronization of data.  It is always
// sent from the client to the target.
//
message SubscribeRequest {
  oneof request {
    SubscriptionList subscribe = 1;
    Heartbeat heartbeat = 2;         // See description for Heartbeat
    SyncRequest sync = 3;            // See description for SyncRequest
    AliasList aliases = 4;
  }
  Proxies proxy = 5;                 // See description in Proxies
}

// Proxies is a list of proxies to use to get to the target.  The first proxy
// listed is the the next hop.  Actual targets ignore the proxy field (it should
// not be set when the request reaches the target).
//
// The target_name is an optional informational field describing the ultimate
// destination of the subscribe request.  This is useful for proxies when
// reporting errors.
message Proxies {
  string target_name = 1;
  repeated Proxy proxy = 2;
}

// A Proxy represents a proxy service to use when connecting to the device.
message Proxy {
  string address = 1;  // IP address of the proxy
  string name = 2;     // optional informational name for the proxy
}

// SubscriptionList contains the list of individual subscriptions.  A
// SubscriptionList is only valid if all of the contained subscriptions are
// valid.
//
// If once is set to true, the request is of mode Once, as described above.  If
// poll_interal is non-zero, the request is a Poll, as described above.  If
// neither once nor poll_interval are set, the mode is Streaming, as described
// above.
//
// If prefix is set then all subscriptions in the list and all notifications
// generated are relative to prefix.
//
// If poll_interval is not set, then a SubscriptionList must only be sent once.
// If poll_interval is set, the SubscriptionLists following the initial
// SubscriptionList must only contain a poll_interval.
//
// If qos is provided then marking is the qos marking to use for this session.
// The target should use this qos marking, if supported.
//
// In the event of overlapping subscription, the most specific subscription for
// a value is used.  For example, if the following two subscriptions were made:
//
//  /interfaces/interfaces/*/state
//  /interfaces/interfaces/*/state/counters
//
// Then values in state outside of counters would be subject to the first
// subscription.  Values inside of counters would be subject to the second
// subscription.
message SubscriptionList {
  Path prefix = 1;
  repeated Subscription subscription = 2;
  bool use_aliases = 3;  // client accepts target defined aliases
  QOSMarking qos = 4;    // QOS marking level target should use.
  oneof mode {
    bool once = 5;
    uint64 poll_interval = 6;
  }
}

// Subscription contains a path as well as information on how two send
// notifications.
//
// A Subscription contains subscription information for a single path.  The path
// may be either a leaf node or a directory node in the tree.  When subscribing
// for a directory node, all nodes below it are automatically included in the
// subscription.
//
// If mode is ON_CHANGE, then the target must either be able to send
// notifcations each time a value changes or reject the subscription.  This is
// typically used for events.  The sample_interval is ignored when the mode in
// ON_CHANGE.
//
// If mode is SAMPLE, the target must coalesce notifcations based on the
// provided sample_interval.  This is typically used for aggregating values
// (i.e., counters).  The sample_interval, if not 0, is the number of
// nanoseconds between updates.  If 0, the interval is selected by the target.
// If the target cannot support the supplied sample_interval, the Subscription
// must be rejected.  The sample_interval is only used for subscriptions in
// streaming mode.  The sample_interval is ignored if mode is not SAMPLE.
//
// (Setting mode to SAMPLE and sample_interval to 0 is functionally the
// same as setting mode to TARGET_DEFINED.)
//
// The suppress_redundant field, if true, indicates the target should not send
// notifications for fields that are unchanged since.  This value is ignored
// if mode is not SAMPLE.
//
// The heartbeat_interval field specifies how frequently an unchanged value must
// be sent regardless of the suppress_redundant field.  A value of 0 indicates
// there is no heartbeat_interval and values only need to be sent when changed.
// The target must reject a subscription if it cannot support the requested
// heartbeat_interval.  This value is ignored if mode is not SAMPLE.
message Subscription {
  Path path = 1;
  SubscriptionMode mode = 2;
  uint64 sample_interval = 3;      // nanoseconds between updates
  bool suppress_redundant = 4;     // do not send updates for unchanged values
  uint64 heartbeat_interval = 5;   // maximum slient period in nanoseconds
}

// SubscriptionMode mode informs the target how notifications should be
// delivered, as they change or coalesced.  When the mode is TARGET_DEFINED the
// target chooses the mode the best suits the value.  When the mode is
// ON_CHANGE, the target must send a notification each time the value changes.
// When the mode is SAMPLE, the target send notifications at some sampling
// interval.
enum SubscriptionMode {
  TARGET_DEFINED = 0; // target determines mode
  ON_CHANGE      = 1; // send notifcation on change (event mode)
  SAMPLE         = 2; // coalesce values (sampled mode)
}

// A QOSMarking describes the QOS marking to use, if supported by the server.
message QOSMarking {
  uint32 marking = 1;
}

// An AliasList represents a list of aliases.
message AliasList {
  repeated Alias alias = 1;
}

// An Alias specifies a preferred client defined alias for a specified path.  An
// Alias is only sent from the client to the target.  An alias is typically one
// element and is much shorter than the provided path.  A target should
// substitute alias for path in Notifications.  Targets may ignore Alias
// messages.
//
// The path must be fully expanded and not use an alias.
//
// If alias is set and path is not then the alias must no longer be used by the
// target, once received.  A client may still see Notifications using the alias
// that were generated prior to the target receiving the request to stop using
// the alias.
message Alias {
  Path path = 1;
  Path alias = 2;
}

// A SyncRequest requests that all values identified by path be resent.  The
// target should respond with a series of updates and then a sync_response with
// the provided id, which should not be zero.
//
// A target is suggested to keep a timestamp of when the SyncRequest starts,
// followed by notifications, all of which are past the starting timestamp.
// Before sending the sync_response, a delete for each of the paths should be
// made with the starting timestamp.  This will assure the client removes all
// stale data that was not part of the update.
//
// If prefix is set, each path is relative to prefix.
message SyncRequest {
   uint64 id = 1;
   Path prefix = 2;
   repeated Path path = 3;
}

// A SubscribeResponse is always sent from the target to the client.
message SubscribeResponse {
  oneof response {
    Notification update = 1;
    Heartbeat heartbeat = 2;  // See description for Heartbeat
    uint64 sync_response = 3; // See description for SyncRequest
  }
}

// A Heartbeat requests a (possibly repeated) response from the remote side.
message Heartbeat {
  // interval is the maximum amount of time, in nanoseconds, between subsequent
  // messages from the remote side.  An empty message may be sent if no other
  // messages are pending.  If interval is 0 then the remote must immediately
  // respond with a (possibly empty) message.
  uint64 interval = 1;
}

// UDPWrapper adds metadata necessary for encapsulating a list of notifications
// into a UDP packet.  It adds the ability to identify the agent that originated
// the Notifications, detect packet loss, and identify latency introduced by
// the target wrapping notifications.
//
// The target should keep the total size of a serialized UDPWrapper message
// small enough to not cause IP packet fragmentation.
message UDPWrapper {
  // ID Identifies the device (e.g., Loopback IP address, linecard, ...)
  // TODO(borman): Add examples.  Perhaps Agent/module/submodule for juniper.
  Path id = 1;

  // Optional Epoch time of when the message is queued for transmit.
  // Useful to quantify delay between message generation and transmission.
  uint64 transmit_timestamp = 2;

  // The sequence_number must start at 1 and increment by 1 for each new packet
  // sent.  A client may use this to determine if a packet was lost.
  uint64 sequence_number = 3;

  repeated Notification notification = 4;
}
<commit_msg>State explicitly that polling mode is optional.<commit_after>syntax = "proto3";

import "google/protobuf/any.proto";

// Package openconfig defines the gRPC service for getting and setting the
// OpenConfig configuration and state of a network device.
//
// This package and its contents have not been ratified by OpenConfig.  It is
// a working proposal by Google.
package openconfig;

service OpenConfig {
  // Get requests a single snapshot of specified data.  A Get request may
  // contain a hint that the request will be repeated (i.e., polling).
  rpc Get(GetRequest) returns (GetResponse);

  // GetModels returns the current YANG models supported by the device.
  rpc GetModels(GetModelsRequest) returns (GetModelsResponse);

  // Set sets the paths contained in the SetRequest to the values If a path does
  // not exist, or is read-only the SetResponse will return an error.  All paths
  // in the SetRequest must be valid or the entire request must be rejected.  If
  // a path specifies a node, rather than the leaf, then the value must be the
  // values of the node's children encoded in JSON.  Binary data in the tree
  // must be base64 encoded.
  rpc Set(stream SetRequest) returns (stream SetResponse);

  // Subscribe subscribes for streaming updates.  Streaming updates are provided
  // as a series of Notifications, each of which update a portion of the tree.
  // The target must send the current values of all subscribed paths at the
  // start of the stream, followed by a sync_response of 0.
  //
  // A Subscription operates in one of three modes.
  //
  // Streaming:  This is the default mode.  The target sends continual updates
  // of each value as specified by each subscription's sample_interval.  The
  // client may request the target to resend the current value of a set of paths
  // by sending a SyncRequest.
  //
  // Once: This mode is specified by setting once to true in the
  // SubscriptionRequest.  The target must close the stream after sending the
  // sync_response of 0.  The target should only send each value once.
  //
  // Poll: This mode is the equivalent of periodic Once requests but sent over a
  // single stream.  This is more efficient than sending multiple Once requests
  // as the target only need parse the subscription once.  It also has an
  // advantage over Streaming as the client is in control of when the target
  // should send data again.
  //
  // To poll, the client sends a SubscriptionRequest with poll_interval set to
  // exepected length of time, in nanoseconds, until the next poll.  The target
  // respods by sending each subscribed value once followed by a sync_resposne
  // of 0.  For each following poll, the client sends a SubscriptionRequest on
  // the same stream with only poll_interval set with the next expected
  // interval.  The target again responses with each subscribed value once
  // followed by a sync_response of 0.
  //
  // Polling mode is optional.  If a target does not support the polling mode,
  // it must reject any request with the poll_interval set.
  rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeResponse);
}

// A Notification is a list of updates to apply.  Deletes are a list of paths to
// delete as long as their data is older than timestamp.  Deleting nodes deletes
// all values below the node that are older than timestamp.  Deletes are
// performed after updates are applied.  Delete paths are created by
// concatenating the prefix, if present, with the individual paths.
//
// Update paths are created by concatenating the prefix, if present, with the
// paths contained in the Updates.
//
// It is valid to have a path be both in an update and match a delete.  The
// deletion will only delete values that are older than this update.
//
// Each notification should contain at most a single update for a given path.
// If a nonconforming implementation does send multiple updates for a given path
// in a single notification, all but the final update should be ignored.
//
// The prefix should normally be the longest common prefix to all the individual
// update and delete path.  This reduces the repetition of the common prefix in
// each update and/or delete.  The individual updates and deletes also are a
// Path (repeated list of elements), allowing a notification such as:
//
//   prefix: /a/b/c
//   update: {
//     path: d
//     value: x
//   }
//   update: {
//     path: e/f
//     value: y
//   }
//   update: {
//     path: e/g
//     value: z
//   }
//
// The prefix may begin with an alias.  An alias is a Path with 1 or more
// elements, which maps to another Path.  Aliases may be defined by either the
// target or the client.  Target defined aliases are limited to a single
// element.  Aliases are client specific (though a target may define the same
// alias for multiple clients).
//
// The target defines an alias by sending a Notification that has alias set and
// a non-empty prefix. When alias is set, a Notification need not provide
// updates or deletes.  If the alias was previously defined, it is over ridden
// with the new definition.  Once defined, the target may send the value of
// alias as the first element of a prefix.  A target must not send target
// defined aliases to clients that do not specify the use_aliases option in the
// initial SubscriptionList message.  A target does not need to define aliases
// even if the client does specify the use_aliases option in the initial
// SubscriptionLlist message.
//
// Clients define aliases by sending a SubscriptionRequest with aliases set.
//
// A target should use a define alias when possible, but is not required to.  A
// target may ignore client defined aliases.
//
// Clients should not define aliases that valid paths in the data tree.  The
// target must not define aliases that valid paths in the dat tree.
//
// If a target sends a notification with alias set, but not prefix, then it is
// indicating it will no longer use this alias.  The client may delete this
// alias from its list of aliases.  A target may not delete an alias defined by
// the client.  It is implementation dependent on what happens if the client
// defines an alias that is also defined by the target.
//
// Aliases must not be used in UDP packets.
//
// If a client sets the use_aliases option, or defines aliases, in the initial
// SubscriptionList message, then it must always check the initial elements of a
// prefix against the list of known aliases, expanding the prefix as needed.
// Aliases must always be defined as fully expanded prefixes.  Only single alias
// lookup is needed per Notification.
//
// Target defined aliases may be any unique string.  A target may choose to use
// a unique prefix for aliases to make them visually distinct.  For example, a
// target might construct all aliases as an @ character followed by a decimal or
// hexadecimal number (perhaps a hashed address in memory).
//
// Example:
//
// Define @42 as an alias:
//
//   timestamp: 1439416376123456789
//   prefix: "this_is"
//   prefix: "a_long"
//   prefix: "prefix"
//   alias: "@42
//
// Use @42 as an alias to set /this_is/a_long/prefix/Ethernet0/0/1/in-octets to
// 17:
//
//   timestamp: 1439416376456456456
//   prefix: "@42"
//   prefix: "Ethernet0/0/1"
//   update: {
//     path: {
//       element: "in-octets"
//     }
//     value: 17
//   }
//
// Delete the alias @42:
//
//   timestamp: 1439416376987654321
//   alias: @42
message Notification {
  int64 timestamp = 1;
  Path prefix = 2;
  string alias = 3;
  repeated Update update = 4;
  repeated Path delete = 5;
}

// An Update maps a path to a value.
//
// In a Notification, an Update represents a new or updated value for path.  The
// absolute path name is the concatenation of the Notification prefix and the
// Update path.  Updates are only sent by the target.  Path must always specify
// a leaf node.  Value should be a scalar value (e.g., if Value is JSON encoded
// then the value 123 is acceptable, but {"x":123} is not).
//
// In a SetRequest, an Update contains a path to a read-write node and an
// optional value.  The absolute path name is the concatenation of the
// SetRequest prefix and the Update path The path may reference either a
// directory or leaf node.  If value is not present then path, and all its
// subelements, should be removed.  If value set and path references a directory
// node, the value is the JSON encoded tree of values below that node,
// otherwise, if the value is a scalar and may be encoded in JSON are as raw
// BYTES.  the value
//
// For an example of updating a directory node, consider a tree that has the
// following values:
//
//   /a/b/c: 1
//   /a/b/d: 2
//   /a/b/e: 3
//
// And an Update of
//
//   Path: /a/b
//   Value: "{c: 4, f: 5}"
//
// The result is that /a/b/d and /a/b/e are removed, /a/b/c now has the value of
// 4, and /a/b/f is added with the value of 5.
message Update {
   Path path = 1;
   Value value = 2;
}

// A Path represents an open config path as a list of strings, one element
// per string.
message Path {
  repeated string element = 1;
}

// A Value is either raw data or a JSON encoded value.  An enumerated value is
// of type JSON, with the numeric value in the value field and the name of the
// enumerated value in the name field.
message Value {
  bytes value = 1;
  Type type = 2;
  string name = 3;
}

// A Type describes what format a Value's data is encoded in.
enum Type {
  JSON = 0;
  BYTES = 1;
}

// GetModelsRequest contains a list of models to return.  If no queries are
// specified, all currently support models will be returned.  ModelReturnType
// specifies the format of the model to return.  By default, only summaries will
// be returned.
message GetModelsRequest {
  // Type selects to return only the summary model information or
  // the full YANG model as bytes.  The caller is responsible for extracting the
  // YANG model from the bytes.
  enum Type {
    SUMMARY = 0; // Request only name, namespace, version information.
    DETAIL = 1;  // Request the YANG model as well has summary information.
  }
  Type request_type = 1;
  ModelQuery query = 2;
}

// ModelQuery contains a name and/or namespace regex pattern to match against
// supported models on the system.
message ModelQuery {
  string name = 1;      // re2 pattern match of the model name.
  string namespace = 2; // re2 pattern match of the model namespace.
  string version = 3;   // re2 pattern match of the model version.
}

// GetModelsResponse returns a list of models supported by the system.
message GetModelsResponse {
  // List of models supported by the system.
  repeated ModelData models = 1;
}

// ModelData contains the summary information for the model as well as the
// actual model data if requested.
message ModelData {
  string name = 1;      // name of the model.
  string namespace = 2; // namespace of the model.
  string version = 3;   // version supported.
  bytes data = 4;       // byte data of the YANG text file.
}

// A GetRequest requests all the values identified by path be returns in a
// single GetResponse message.
//
// If cache_interval is provided and is non-zero number of nanoseconds, it is
// a hint of when this get request will be repeated in the future.
message GetRequest {
  Path prefix = 1;          // If set, each path is realitve to prefix
  repeated Path path = 2;   // List of paths to return information for
  // Type defines the mode that Get should use (GET_DATA_COMMANDS in the
  // YANG schema).  Only ALL is required by all implementation.
  enum Type {
    ALL         = 0; // Return all data
    CONFIG      = 1; // Only return values in Config containers
    STATE       = 2; // Only return values in State containers
    OPERATIONAL = 3; // Only values in State containers not modeled in Config
  }
  Type type = 3;         // Limit what type of values are returned.
  int64 cache_interval = 4;
}

message GetResponse {
  repeated Notification notification = 1;
}

// A SetRequest contains an optional prefix, a list of zero or more Paths to
// delete, a list of zero or more paths to replace, and a list of zero of more
// paths to update.  Deletes should appear to happen first, followed by
// replacements, followed by updates.
//
// If the path lists a node, rather than leaf, the value is presented in JSON.
// When included in replace, it is as if the path was first deleted.  When
// included in update, the value aguments the existing value, if any.
//
// The target must either apply all the deletes, replacements, and updates or
// return an error.  The deletes, replacements, and updates should appear to be
// atomically applied.
message SetRequest {
  Path prefix = 1;
  repeated Path delete = 2;
  repeated Update replace = 3;
  repeated Update update = 4;
}

// A SetResponse contains responses to a SetRequest.  The optional prefix is
// applied to all paths in response.  Each path provided by a SetRequest needs a
// response, but there need not be a 1:1 correspondence between SetRequests and
// SetResponses (e.g., the target may issue a single response to multiple
// requests, or multiple responses to a single request).
message SetResponse {
  Path prefix = 1;
  repeated UpdateResponse response = 2;
}

// An UpdateResponse contains the response for a single path Update.
message UpdateResponse {
  // The timestamp is the time, in nanoseconds since the epoch, that a Set was
  // accepted (i.e., the request was valid).  It does not imply the value was
  // actually propagated to an underlying datastore.
  int64 timestamp = 1;
  Path path = 2;       // path provided in SetRequest.
  Error error = 3;     // optional error, if set, timestamp is optional
}

// An Error contains information about why a particular request failed.
//
// The canonical error codes are defined for each language.
//
//   Go:   import "google.golang.org/grpc/codes"
//   C++:  #include <grpc++/status_code_enum.h>
//   Java: import static io.grpc.Status.Code;
//   C:    #include <grpc/status.h>
//   C#:   using Grpc.Core;
message Error {
  uint32 code = 1;                // Canonical grpc error code
  string message = 2;             // Human readable error
  google.protobuf.Any data = 3;   // optional additional information
}

// A SubscribeRequest is either a subscription request, a change to the
// heartbeat rate, or a request for resynchronization of data.  It is always
// sent from the client to the target.
//
message SubscribeRequest {
  oneof request {
    SubscriptionList subscribe = 1;
    Heartbeat heartbeat = 2;         // See description for Heartbeat
    SyncRequest sync = 3;            // See description for SyncRequest
    AliasList aliases = 4;
  }
  Proxies proxy = 5;                 // See description in Proxies
}

// Proxies is a list of proxies to use to get to the target.  The first proxy
// listed is the the next hop.  Actual targets ignore the proxy field (it should
// not be set when the request reaches the target).
//
// The target_name is an optional informational field describing the ultimate
// destination of the subscribe request.  This is useful for proxies when
// reporting errors.
message Proxies {
  string target_name = 1;
  repeated Proxy proxy = 2;
}

// A Proxy represents a proxy service to use when connecting to the device.
message Proxy {
  string address = 1;  // IP address of the proxy
  string name = 2;     // optional informational name for the proxy
}

// SubscriptionList contains the list of individual subscriptions.  A
// SubscriptionList is only valid if all of the contained subscriptions are
// valid.
//
// If once is set to true, the request is of mode Once, as described above.  If
// poll_interal is non-zero, the request is a Poll, as described above.  If
// neither once nor poll_interval are set, the mode is Streaming, as described
// above.
//
// If prefix is set then all subscriptions in the list and all notifications
// generated are relative to prefix.
//
// If poll_interval is not set, then a SubscriptionList must only be sent once.
// If poll_interval is set, the SubscriptionLists following the initial
// SubscriptionList must only contain a poll_interval.
//
// If qos is provided then marking is the qos marking to use for this session.
// The target should use this qos marking, if supported.
//
// In the event of overlapping subscription, the most specific subscription for
// a value is used.  For example, if the following two subscriptions were made:
//
//  /interfaces/interfaces/*/state
//  /interfaces/interfaces/*/state/counters
//
// Then values in state outside of counters would be subject to the first
// subscription.  Values inside of counters would be subject to the second
// subscription.
message SubscriptionList {
  Path prefix = 1;
  repeated Subscription subscription = 2;
  bool use_aliases = 3;  // client accepts target defined aliases
  QOSMarking qos = 4;    // QOS marking level target should use.
  oneof mode {
    bool once = 5;
    uint64 poll_interval = 6;
  }
}

// Subscription contains a path as well as information on how two send
// notifications.
//
// A Subscription contains subscription information for a single path.  The path
// may be either a leaf node or a directory node in the tree.  When subscribing
// for a directory node, all nodes below it are automatically included in the
// subscription.
//
// If mode is ON_CHANGE, then the target must either be able to send
// notifcations each time a value changes or reject the subscription.  This is
// typically used for events.  The sample_interval is ignored when the mode in
// ON_CHANGE.
//
// If mode is SAMPLE, the target must coalesce notifcations based on the
// provided sample_interval.  This is typically used for aggregating values
// (i.e., counters).  The sample_interval, if not 0, is the number of
// nanoseconds between updates.  If 0, the interval is selected by the target.
// If the target cannot support the supplied sample_interval, the Subscription
// must be rejected.  The sample_interval is only used for subscriptions in
// streaming mode.  The sample_interval is ignored if mode is not SAMPLE.
//
// (Setting mode to SAMPLE and sample_interval to 0 is functionally the
// same as setting mode to TARGET_DEFINED.)
//
// The suppress_redundant field, if true, indicates the target should not send
// notifications for fields that are unchanged since.  This value is ignored
// if mode is not SAMPLE.
//
// The heartbeat_interval field specifies how frequently an unchanged value must
// be sent regardless of the suppress_redundant field.  A value of 0 indicates
// there is no heartbeat_interval and values only need to be sent when changed.
// The target must reject a subscription if it cannot support the requested
// heartbeat_interval.  This value is ignored if mode is not SAMPLE.
message Subscription {
  Path path = 1;
  SubscriptionMode mode = 2;
  uint64 sample_interval = 3;      // nanoseconds between updates
  bool suppress_redundant = 4;     // do not send updates for unchanged values
  uint64 heartbeat_interval = 5;   // maximum slient period in nanoseconds
}

// SubscriptionMode mode informs the target how notifications should be
// delivered, as they change or coalesced.  When the mode is TARGET_DEFINED the
// target chooses the mode the best suits the value.  When the mode is
// ON_CHANGE, the target must send a notification each time the value changes.
// When the mode is SAMPLE, the target send notifications at some sampling
// interval.
enum SubscriptionMode {
  TARGET_DEFINED = 0; // target determines mode
  ON_CHANGE      = 1; // send notifcation on change (event mode)
  SAMPLE         = 2; // coalesce values (sampled mode)
}

// A QOSMarking describes the QOS marking to use, if supported by the server.
message QOSMarking {
  uint32 marking = 1;
}

// An AliasList represents a list of aliases.
message AliasList {
  repeated Alias alias = 1;
}

// An Alias specifies a preferred client defined alias for a specified path.  An
// Alias is only sent from the client to the target.  An alias is typically one
// element and is much shorter than the provided path.  A target should
// substitute alias for path in Notifications.  Targets may ignore Alias
// messages.
//
// The path must be fully expanded and not use an alias.
//
// If alias is set and path is not then the alias must no longer be used by the
// target, once received.  A client may still see Notifications using the alias
// that were generated prior to the target receiving the request to stop using
// the alias.
message Alias {
  Path path = 1;
  Path alias = 2;
}

// A SyncRequest requests that all values identified by path be resent.  The
// target should respond with a series of updates and then a sync_response with
// the provided id, which should not be zero.
//
// A target is suggested to keep a timestamp of when the SyncRequest starts,
// followed by notifications, all of which are past the starting timestamp.
// Before sending the sync_response, a delete for each of the paths should be
// made with the starting timestamp.  This will assure the client removes all
// stale data that was not part of the update.
//
// If prefix is set, each path is relative to prefix.
message SyncRequest {
   uint64 id = 1;
   Path prefix = 2;
   repeated Path path = 3;
}

// A SubscribeResponse is always sent from the target to the client.
message SubscribeResponse {
  oneof response {
    Notification update = 1;
    Heartbeat heartbeat = 2;  // See description for Heartbeat
    uint64 sync_response = 3; // See description for SyncRequest
  }
}

// A Heartbeat requests a (possibly repeated) response from the remote side.
message Heartbeat {
  // interval is the maximum amount of time, in nanoseconds, between subsequent
  // messages from the remote side.  An empty message may be sent if no other
  // messages are pending.  If interval is 0 then the remote must immediately
  // respond with a (possibly empty) message.
  uint64 interval = 1;
}

// UDPWrapper adds metadata necessary for encapsulating a list of notifications
// into a UDP packet.  It adds the ability to identify the agent that originated
// the Notifications, detect packet loss, and identify latency introduced by
// the target wrapping notifications.
//
// The target should keep the total size of a serialized UDPWrapper message
// small enough to not cause IP packet fragmentation.
message UDPWrapper {
  // ID Identifies the device (e.g., Loopback IP address, linecard, ...)
  // TODO(borman): Add examples.  Perhaps Agent/module/submodule for juniper.
  Path id = 1;

  // Optional Epoch time of when the message is queued for transmit.
  // Useful to quantify delay between message generation and transmission.
  uint64 transmit_timestamp = 2;

  // The sequence_number must start at 1 and increment by 1 for each new packet
  // sent.  A client may use this to determine if a packet was lost.
  uint64 sequence_number = 3;

  repeated Notification notification = 4;
}

{'fraction_non_alphanumeric': 0.06970053615797045, 'fraction_numerical': 0.009676997515365503, 'mean_word_length': 3.0016570730856444, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6488834', 'n_tokens_mistral': 12561, 'n_tokens_neox': 11964, 'n_words': 6676}