NDK Operations#
When NDK application is installed on SR Linux it interfaces with the NDK service via gRPC. Regardless of programming language the agent is written in, every application will perform the following basic NDK operations (as shown in Fig. 1):
- Establish gRPC channel with NDK manager and instantiate an NDK client
- Register the agent with the NDK manager
- Register notification streams for different types of NDK services (config, lldp, interface, etc.)
- Start streaming notifications
- Handle the streamed notifications
- Perform some work based on the received notifications
- Update agent's state data if required
- Exit gracefully by unregistering the agent
To better understand the steps an agent undergoes, we will explain them in a language-neutral manner. For language-specific implementations, read the "Developing with NDK" chapter.
Creating NDK Manager Client#
NDK agents communicate with gRPC-based NDK service by means of remote procedure calls (RPC). An RPC generally takes in a client request message and returns a response message from the server.
First, a gRPC channel must be established with the NDK manager application running on SR Linux1. By default, NDK server listens for connections on a unix socket unix:///opt/srlinux/var/run/sr_sdk_service_manager:50053
2 and doesn't require any authentication. NDK app is expected to connect to this socket to establish gRPC.
sequenceDiagram
participant N as NDK app
participant S as NDK Manager
N->>S: Open gRPC channel
Note over N,S: gRPC channel established
create participant MC as NDK Manager Client
N-->>MC: Create NDK Manager Client
activate MC
Note over MC: NDK Manager Client<br/>interacts with SdkMgrService
Once the gRPC channel is set up, a gRPC client (often called the stub) needs to be created to perform RPCs. In gRPC, each service requires its own client and in NDK the SdkMgrService
service is the first service that agents interact with.
Therefore, users first need to create the NDK Manager Client (Mgr Client in Fig. 1) that will be able to call RPCs of SdkMgrService
.
Tip
In the proto files and the generated NDK documentation the NDK services have Sdk
in their name. While in fact NDK is a fancy name for an SDK, we would like to call the client of the SdkMgrService
the NDK Manager Client.
Agent registration#
With the gRPC channel set up and the NDK Manager Client created, we can start using the NDK service. The first mandatory step is the agent registration with the NDK Manager. At this step NDK initializes the state of our agent, creates the IDB tables and assigns an ID to our application.
sequenceDiagram
participant NMC as NDK Manager Client
participant SDK as SDK Manager Service
NMC->>SDK: AgentRegister
SDK-->>NMC: AgentRegistrationResponse
The registration process is carried out by calling AgentRegister
RPC of the SdkMgrService
. A AgentRegistrationResponse
is returned (omitted in Fig. 1) with the status of the registration process and application ID assigned to the app by the NDK.
Subscribing to notifications#
Remember we said that NDK Agents can interact with other native SR Linux apps? The interaction is done by subscribing to notifications from other SR Linux applications with NDK Manager acting like a gateway between your application and the messaging bus that all SR Linux applications communicate over.
For example, an NDK app can get information from Network Instance, Config, LLDP, BFD and other applications by requesting subscription to notification updates from these applications:
sequenceDiagram
participant App as NDK App
participant NDK as NDK Service
participant IDB as Messaging bus<br/>IDB
participant LLDP as LLDP Manager
App->>NDK: I want to receive LLDP notifications
NDK->>IDB: Subscribing to LLDP notifications
LLDP-->>IDB: LLDP event
IDB-->>NDK: LLDP event
NDK-->>App: LLDP event
Let's have a closer look at what it takes to subscribe to notifications from other SR Linux applications.
Creating notification stream#
Prior to subscribing to any application's notifications a subscription stream needs to be created. A client of SdkMgrService
calls NotificationRegister
RPC providing NotificationRegistrationRequest
message with the op
field set to Create
and other fields absent.
Other values of Registration Request operations field
NotificationRegistrationRequest
message's field op
(short for "operation") may have one of the following values:
Create
creates a subscription stream and returns aStreamId
that is used when adding subscriptions with theAddSubscription
operation.Delete
deletes the existing subscription stream that has a particularSubId
.AddSubscription
adds a subscription. The stream will now be able to stream notifications of that subscription type (e.g., Intf, NwInst, etc).DeleteSubscription
deletes the previously added subscription.
NDK Manager responds with NotificationRegisterResponse
message with the allocated stream_id
value. The stream has been created, and the subscriptions can now be added to the created stream.
Adding subscriptions#
With subscription stream allocated we can proceed with adding one or more subscriptions to it. SdkMgrService
service offers NotificationRegister
RPC to add subscriptions to the stream. The RPC uses the same NotificationRegistrationRequest
message (step 4 in Fig. 1) as we used to create the stream, but now with the following fields set:
stream_id
set to an obtained value from the previous stepop
is set toAddSubscription
- one of the supported
subscription_types
according to the desired service notifications. For example, if we are interested to receiveConfig
notifications, thenconfig
field of typeConfigSubscriptionRequest
is set.
NotificationRegisterResponse
message (step 5 in Fig. 1) is returned and contains the same stream_id
value and now also the sub_id
value - a subscription identifier. At this point NDK application indicated its intention to receive notifications from certain services, but the notification streams haven't been started yet.
Streaming notifications#
Requesting applications to send notifications is done by interacting with SdkNotificationService
. As this is another gRPC service, it requires its own client - Notification client. Steps 6 and 7 in Fig. 1 show the interaction between the Notification Client and the Notification service.
To initiate streaming of the notifications requested in the previous step the Notification Client calls NotificationStream
RPC with NotificationStreamRequest
message with stream_id
field set to the ID of a stream to be used. This RPC returns a stream of NotificationStreamResponse
, which makes this RPC to be classified as "server streaming RPC".
Server-streaming RPC
A server-streaming RPC is similar to a unary RPC, except that the server returns a stream of messages in response to a client's request.
After sending all its messages, the server's status details (status code and optional status message) and optional trailing metadata are sent to the client. This completes processing on the server side. The client completes once it has all the server's messages.
The Notification client starts to receive a stream of NotificationStreamResponse
messages where each message contains one or more Notification
message. The Notification
message itself will contain a field with one of the subscription_types
notifications, which will be set in accordance to the type of the notification requested on this stream in the Adding subscriptions step.
In our example, we sent ConfigSubscriptionRequest
inside the NotificationRegisterRequest
, hence the notifications that we will get back for that stream_id
will contain ConfigNotification
messages inside Notification
of a NotificationStreamResponse
.
Handling notifications#
Now we reached the point where our custom Application can start doing actual work. The application receives a stream of notifications from the NDK Manager based on the subscriptions it requested.
The application needs to handle the notifications and perform some work based on the received data.
For example, if the application requested to receive Config
notifications, it will receive a stream of ConfigNotification
messages containing the configuration changes that happened on the SR Linux system for this application's configuration. The application then can parse the received data and perform some work based on it.
The Server streaming RPC will provide notifications till the last available one and block awaiting more notifications to send; the application then reads out the incoming notifications and handles the messages contained within them. Some notification messages have SyncStart
and SyncEnd
messages that indicate the start and end of a stream of notifications. The application can use these messages to synchronize its state with the SR Linux system.
For example, when streaming out routes from the RIB table, the application can use SyncStart
and SyncEnd
messages to know when the stream of routes is complete and can start processing the received routes.
Handling application's configuration and state#
As any other "regular" application, NDK applications can have their own configuration and state modelled with YANG and injected in the global config/state of the SR Linux NOS.
When NDK developer defines the YANG model for the application, they can model configuration and state data that will be accessible via CLI and all other management interfaces. The configuration data can be edited by a user via common management interfaces and delivered to the application via NDK. This workflow enables configuration management of the application via the same management interfaces as the rest of the SR Linux system.
Once configured, the application may need to update its state data based on the received notifications and the work it carried out. The state of the application becomes part of the SR Linux state datastore and is accessible via all management interfaces.
Updating or creating agent's state is done with TelemetryAddOrUpdate
RPC that uses TelemetryUpdateRequest
message with a list of TelemetryInfo
messages. Each TelemetryInfo
message contains a key
field that points to a subtree of agent's YANG model that needs to be updated with the JSON data contained within the data
field.
Exiting gracefully#
When an agent needs to stop its operation and/or be removed from the SR Linux system, it needs to unregister by invoking AgentUnRegister
RPC of the SdkMgrService
. The gRPC connection to the NDK server needs to be closed.
When unregistered, the agent's state data will be removed from SR Linux system and will no longer be accessible to any of the management interfaces.