-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Config Subscription gNMI Extension #169
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,11 +28,12 @@ option go_package = "github.com/openconfig/gnmi/proto/gnmi_ext"; | |
// The Extension message contains a single gNMI extension. | ||
message Extension { | ||
oneof ext { | ||
RegisteredExtension registered_ext = 1; // A registered extension. | ||
RegisteredExtension registered_ext = 1; // A registered extension. | ||
// Well known extensions. | ||
MasterArbitration master_arbitration = 2; // Master arbitration extension. | ||
History history = 3; // History extension. | ||
Commit commit = 4; // Commit confirmed extension. | ||
MasterArbitration master_arbitration = 2; // Master arbitration extension. | ||
History history = 3; // History extension. | ||
Commit commit = 4; // Commit confirmed extension. | ||
ConfigSubscription config_subscription = 6; // Config Subscription extension. | ||
} | ||
} | ||
|
||
|
@@ -131,3 +132,30 @@ message CommitConfirm {} | |
// CommitCancel is used to cancel an on-going commit. It hold additional | ||
// parameter requried for cancel action. | ||
message CommitCancel {} | ||
|
||
// ConfigSubscription extension allows clients to subscribe to configuration | ||
// schema nodes only. | ||
message ConfigSubscription { | ||
oneof action { | ||
// ConfigSubscriptionStart is sent by the server in the SubscribeRequest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The documentation in the use cases doesn't seem to correspond to this, and it seems like there's overloading of these fields. a) the client sends something from the target with b) I'd suggest making this a separate extension -- or making this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a typo in the comment, it should be It's true that receiving
If we add a field (called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO, if we add a field to the [0]: for example, if this extension implies There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @karimra do you want to add a extension field to the Another way to handle this might be to implement a way to get the supported extensions? Then a client can programmatically know if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I was planning to do that in a separate PR if that's ok. |
||
ConfigSubscriptionStart start = 1; | ||
// ConfigSubscriptionSyncDone is sent by the server in the SubscribeResponse | ||
ConfigSubscriptionSyncDone sync_done = 2; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👋 @robshakir
Correct. We are referring to the config data as per RFC 7950 4.2.3. aka. the nodes with config=true yang statement.
100% supportive of this proposal. We feel that this is a vital mgmt interface capability that is required for schemas that do not employ OpenConfig's config/state container composition. If the openconfig/gnmi stakeholders share the same feeling then this is better to be handled in the standard, and not the extension, IMHO.
I am not sure I see how path wildcards can serve as a config/state data elements selector. Don't remember seeing anything of that sorts in the path specification document. I can imagine how custom wildcarding tokens might be used ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few points:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree. Generally speaking, we were referring to the "configuration data nodes" in a schema-language agnostic definition. To project this on a de-facto standard data modeling language - yang -, I used it as an example of what this would mean for a target employing this schema language.
Having a method similar to the GET request would also work for us. We went the extension way to have the changes less intrusive to the spec. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, while I agree we should avoid coupling yang directives into gnmi, it's valid that the concept of 'config' and 'state' are not necessarily yang specific. Also, it seems impractical to require (non-OC) schemas to be modified to include the word 'config' in them. I am ok with adding this. |
||
|
||
// ConfigSubscriptionStart is used to indicate to a target that for a given set | ||
// of paths in the SubscribeRequest, the client wishes to receive updates | ||
// for the configuration schema nodes only. | ||
message ConfigSubscriptionStart {} | ||
|
||
// ConfigSubscriptionSyncDone is sent by the server in the SubscribeResponse | ||
// after all the updates for the configuration schema nodes have been sent. | ||
message ConfigSubscriptionSyncDone { | ||
// ID of a commit confirm operation as assigned by the client | ||
// see Commit Confirm extension for more details. | ||
string commit_confirm_id = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The two values can both be present in the same message. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fwiw, here is a demo that shows how both commit_confirm_id and server_commit_id are both present when commit with confirm is executed |
||
// ID of a commit as might be assigned by the server | ||
// when registering a commit operation. | ||
string server_commit_id = 2; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @robshakir here I would like to address the 2nd part of the original question set.
The need for signaling stems from the fact that the Subscribe RPC lacks a mechanism to mark that a certain snapshot of the data tree has been sent. Verbatim from the spec: That is, it is not possible for a client requesting a subscription to assume that the set of update messages received represent a snapshot of the data tree at a particular point in time. Because configuration management tasks essentially move the system from one state to another using a configuration commit operation, the management system (NMS) can benefit from a long-running subscription stream that would have such markers for a NMS to reliably tell "oh, ok, now all the configuration updates of the data tree I am subscribed to have been received, I see the sync marker". An important path of the sync message is the embedded commit identifiers. By saying that we would just wait till we see the same paths streamed back without a sync message we would loose that correlation between the intended config changes sent and received and wouldn't be able to reconcile the intended change with the data streamed back if necessary in a reactive manner. E.g. what if a third party actor changed the same data node in a different commit and the NMS sees that update and assumes it belongs to the change set it sent? The large part of the sync message usefulness is rooted in the reported commit IDs.
The target sends a sync message whenever the change set is written/committed. For systems that leverage commit operations this means whenever a change set is committed, the updates are first streamed to the NMS and after the target sent all the updates for the associated change set it send the sync message with commit identifiers. Since commit IDs are present in the sync message, the NMS can identify changes it requested vs changes made by other clients (based on the provided commit identifiers). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand. The delineation of a particular change seems a reasonable use case. However, let's think about a few cases we will need to deal with: a) gNMI allows for coalescing of updates -- so if we have some change to b) I'm not sure that If we then add this extension, I presume the initial Following this initial set of updates, then a set of configurable values might change -- and the contract we are establishing here is that the target is able to say "I have finished applying intended state updates for a particular commit" by applying this extension for the last update. Is that correct? If the answer to b) is correct, then the interaction with a) needs to be considered -- what happens the target has "finished" applying an update for commit ID = 1, but in the meantime also made a change for commit ID = 2. It's probably easy to say that in the case that commit ID = 2 is a subset of commit ID = 1, then receiving this extension means that commit ID = 1 has been applied and commit ID = 2 has been applied. The complex case is where they are for the same leaf, and we coalesce the two together. We should not prevent coalescing of these updates since it will mean that there are changes to all gNMI servers to treat this as a new "special" field. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ideally these values shouldn't be coalesced, since a collector would need to know that a commit "happened" and where its boundary is. But if this cannot be guaranteed by some implementations, we can say that if at least one value from a commit has been coalesced then its corresponding
Yes.
Correct. The initial values are streamed to the client just like a regular subscription up until the
The extension with a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This would be a core gNMI specification update -- we specifically allow for this coaelscing as it means that flapping data values, and slow peers have a clean congestion management approach. If there is a case where you want a specific notification that has to be reliably delivered (i.e., that specific update) then it needs to have a unique path, this itself has some scaling considerations that need to be taken into account. I'm not supportive of changing this core element of the specification.
It might be non-deterministic as to what happens -- it depends where we are specifying that this extension is sent. Is it attached to the last leaf to be applied, or is this envisaged to be a separate The alternate design space here is to have a leaf that specifically means this something like
Can we specify this somewhere? It's not clear today that the expectation is that this is applied to every
Again, please can we specify this if this is the preferred behaviour? If so, it seems like this would not be compatible with having a caching collector that works per-path -- since there's simply nothing to cache this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We discussed including the extension with the last update, there is really nothing against it from our implementation point of view. It's just that the IDs are optional; not all commits are commitConfirmed and not all targets can send a server_commit_id.
Such a leaf tells that the commit was applied but it doesn't tell the controller that it received all the notifications related to that commit. Using an on-change subscription with a message signaling that a commit's notifications were streamed is a fast and lightweight way for a client to remain in sync with target config.
The preferred behavior is sending the extension in its own // ConfigSubscriptionSyncDone is sent by the server in the SubscribeResponse
// after all the updates for the configuration schema nodes have been sent.
message ConfigSubscriptionSyncDone {
Yes, as said above nothing against this. But if the goal is to store the commit IDs with the updates, we need to keep in mind that there might not be commit IDs sent in the extension and we would need to include the extension in all the updates with a marker for the last one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
From an implementation perspective -- either the gNMI There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand correctly the above alternative implies that:
For 1) Not all commits are commitConfirmed and not all implementations provide a server commit ID. We didn't want to assume too much on how gNMI implementations are done out there to keep the extension as vendor agnostic as possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @robshakir @dplore, all
We would like to resume the discussions around this extension proposal.
After extensive internal use of this extension we find it particularly fit for a common problem in the network management domain -- configuration deviation/drift detection and reconciliation. We believe it might be useful for operators and other gNMI users.
To summarize, ConfigSubscription extension provides the following capabilities that contribute to the config drift detection use case:
Contrary to Get RPC, Subscribe RPC does not have a toggle to select which category of data nodes to subscribe to (state vs config vs both)
This is important for gNMI applications that are based on yang models without strict state/config separation of data
The
sync_done
message allows a client to identify when all changes for a particular commit have been fully sent by the gNMI server. This ensures it is safe to trigger deviation computation without needing to perform a full resync.These two new capabilities added by this extension to gNMI could (among other use cases) enable a gNMI client to make use of a robust and reactive configuration drift detection/reconciliation mechanism.
When used together, the configuration mananagement system can make use of the streaming nature of gNMI Subscribe RPC to get a rapid deviation detection.
First, it benefits from a lightweight subscription mode when only changes to the configuration datastore elements are being sent as notifications.
And then, by making use of the
sync_done
message in this extension the system can quickly react to the changes made to the configuration data it is subscribed to.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the use case makes sense, we can probably stop selling it and work out the details :-)
The subscription to config only data is fine -- I would be OK with adding something here to
SubscriptionList
that says the the data type similarly toGet
. We can just make the default state of this asBOTH
, which would give a means to be able to be backwards compatible should this field not be specified.