diff --git a/api/go/gosdn/pnd/pnd.pb.go b/api/go/gosdn/pnd/pnd.pb.go
index 8b52d80fe24ce2736647ae104ff754eaa8be9562..b7680a2d65f6d0cde9984ae9e920c01d6f3f2abe 100644
--- a/api/go/gosdn/pnd/pnd.pb.go
+++ b/api/go/gosdn/pnd/pnd.pb.go
@@ -286,6 +286,110 @@ func (Status) EnumDescriptor() ([]byte, []int) {
 	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{4}
 }
 
+type SubscriptionMode int32
+
+const (
+	SubscriptionMode_SUBSCRIPTION_MODE_UNSPECIFIED SubscriptionMode = 0
+	SubscriptionMode_SUBSCRIPTION_MODE_ONCE        SubscriptionMode = 1
+	SubscriptionMode_SUBSCRIPTION_MODE_STREAM      SubscriptionMode = 2
+	SubscriptionMode_SUBSCRIPTION_MODE_POLL        SubscriptionMode = 3
+)
+
+// Enum value maps for SubscriptionMode.
+var (
+	SubscriptionMode_name = map[int32]string{
+		0: "SUBSCRIPTION_MODE_UNSPECIFIED",
+		1: "SUBSCRIPTION_MODE_ONCE",
+		2: "SUBSCRIPTION_MODE_STREAM",
+		3: "SUBSCRIPTION_MODE_POLL",
+	}
+	SubscriptionMode_value = map[string]int32{
+		"SUBSCRIPTION_MODE_UNSPECIFIED": 0,
+		"SUBSCRIPTION_MODE_ONCE":        1,
+		"SUBSCRIPTION_MODE_STREAM":      2,
+		"SUBSCRIPTION_MODE_POLL":        3,
+	}
+)
+
+func (x SubscriptionMode) Enum() *SubscriptionMode {
+	p := new(SubscriptionMode)
+	*p = x
+	return p
+}
+
+func (x SubscriptionMode) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SubscriptionMode) Descriptor() protoreflect.EnumDescriptor {
+	return file_gosdn_pnd_pnd_proto_enumTypes[5].Descriptor()
+}
+
+func (SubscriptionMode) Type() protoreflect.EnumType {
+	return &file_gosdn_pnd_pnd_proto_enumTypes[5]
+}
+
+func (x SubscriptionMode) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use SubscriptionMode.Descriptor instead.
+func (SubscriptionMode) EnumDescriptor() ([]byte, []int) {
+	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{5}
+}
+
+type StreamMode int32
+
+const (
+	StreamMode_STREAM_MODE_UNSPECIFIED    StreamMode = 0
+	StreamMode_STREAM_MODE_TARGET_DEFINED StreamMode = 1 // The target selects the relevant mode for each element.
+	StreamMode_STREAM_MODE_ON_CHANGE      StreamMode = 2 // The target sends an update on element value change.
+	StreamMode_STREAM_MODE_SAMPLE         StreamMode = 3 // The target samples values according to the interval.
+)
+
+// Enum value maps for StreamMode.
+var (
+	StreamMode_name = map[int32]string{
+		0: "STREAM_MODE_UNSPECIFIED",
+		1: "STREAM_MODE_TARGET_DEFINED",
+		2: "STREAM_MODE_ON_CHANGE",
+		3: "STREAM_MODE_SAMPLE",
+	}
+	StreamMode_value = map[string]int32{
+		"STREAM_MODE_UNSPECIFIED":    0,
+		"STREAM_MODE_TARGET_DEFINED": 1,
+		"STREAM_MODE_ON_CHANGE":      2,
+		"STREAM_MODE_SAMPLE":         3,
+	}
+)
+
+func (x StreamMode) Enum() *StreamMode {
+	p := new(StreamMode)
+	*p = x
+	return p
+}
+
+func (x StreamMode) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (StreamMode) Descriptor() protoreflect.EnumDescriptor {
+	return file_gosdn_pnd_pnd_proto_enumTypes[6].Descriptor()
+}
+
+func (StreamMode) Type() protoreflect.EnumType {
+	return &file_gosdn_pnd_pnd_proto_enumTypes[6]
+}
+
+func (x StreamMode) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use StreamMode.Descriptor instead.
+func (StreamMode) EnumDescriptor() ([]byte, []int) {
+	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{6}
+}
+
 type GetOndListRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -2356,6 +2460,260 @@ func (x *DeleteOndResponse) GetStatus() Status {
 	return Status_STATUS_UNSPECIFIED
 }
 
+type SubscribePathRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Timestamp int64             `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Did       string            `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"`
+	Pid       string            `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	Sublist   *SubscriptionList `protobuf:"bytes,4,opt,name=sublist,proto3" json:"sublist,omitempty"`
+}
+
+func (x *SubscribePathRequest) Reset() {
+	*x = SubscribePathRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdn_pnd_pnd_proto_msgTypes[33]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SubscribePathRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SubscribePathRequest) ProtoMessage() {}
+
+func (x *SubscribePathRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_pnd_pnd_proto_msgTypes[33]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SubscribePathRequest.ProtoReflect.Descriptor instead.
+func (*SubscribePathRequest) Descriptor() ([]byte, []int) {
+	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{33}
+}
+
+func (x *SubscribePathRequest) GetTimestamp() int64 {
+	if x != nil {
+		return x.Timestamp
+	}
+	return 0
+}
+
+func (x *SubscribePathRequest) GetDid() string {
+	if x != nil {
+		return x.Did
+	}
+	return ""
+}
+
+func (x *SubscribePathRequest) GetPid() string {
+	if x != nil {
+		return x.Pid
+	}
+	return ""
+}
+
+func (x *SubscribePathRequest) GetSublist() *SubscriptionList {
+	if x != nil {
+		return x.Sublist
+	}
+	return nil
+}
+
+// The mode determines how the target should trigger updates to be sent.
+// Reference: gNMI Specification Section 3.5.1.2
+type SubscriptionList struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Subscription []*Subscription  `protobuf:"bytes,1,rep,name=subscription,proto3" json:"subscription,omitempty"`
+	Mode         SubscriptionMode `protobuf:"varint,2,opt,name=mode,proto3,enum=gosdn.pnd.SubscriptionMode" json:"mode,omitempty"`
+}
+
+func (x *SubscriptionList) Reset() {
+	*x = SubscriptionList{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdn_pnd_pnd_proto_msgTypes[34]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SubscriptionList) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SubscriptionList) ProtoMessage() {}
+
+func (x *SubscriptionList) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_pnd_pnd_proto_msgTypes[34]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SubscriptionList.ProtoReflect.Descriptor instead.
+func (*SubscriptionList) Descriptor() ([]byte, []int) {
+	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{34}
+}
+
+func (x *SubscriptionList) GetSubscription() []*Subscription {
+	if x != nil {
+		return x.Subscription
+	}
+	return nil
+}
+
+func (x *SubscriptionList) GetMode() SubscriptionMode {
+	if x != nil {
+		return x.Mode
+	}
+	return SubscriptionMode_SUBSCRIPTION_MODE_UNSPECIFIED
+}
+
+type Subscription struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Path           string     `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
+	StreamMode     StreamMode `protobuf:"varint,2,opt,name=stream_mode,json=streamMode,proto3,enum=gosdn.pnd.StreamMode" json:"stream_mode,omitempty"`
+	SampleInterval uint64     `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"` // ns between samples in SAMPLE mode.
+}
+
+func (x *Subscription) Reset() {
+	*x = Subscription{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdn_pnd_pnd_proto_msgTypes[35]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Subscription) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Subscription) ProtoMessage() {}
+
+func (x *Subscription) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_pnd_pnd_proto_msgTypes[35]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Subscription.ProtoReflect.Descriptor instead.
+func (*Subscription) Descriptor() ([]byte, []int) {
+	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{35}
+}
+
+func (x *Subscription) GetPath() string {
+	if x != nil {
+		return x.Path
+	}
+	return ""
+}
+
+func (x *Subscription) GetStreamMode() StreamMode {
+	if x != nil {
+		return x.StreamMode
+	}
+	return StreamMode_STREAM_MODE_UNSPECIFIED
+}
+
+func (x *Subscription) GetSampleInterval() uint64 {
+	if x != nil {
+		return x.SampleInterval
+	}
+	return 0
+}
+
+type SubscribePathResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Timestamp int64                `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Status    Status               `protobuf:"varint,2,opt,name=status,proto3,enum=gosdn.pnd.Status" json:"status,omitempty"`
+	Device    []*gnmi.Notification `protobuf:"bytes,3,rep,name=device,proto3" json:"device,omitempty"`
+}
+
+func (x *SubscribePathResponse) Reset() {
+	*x = SubscribePathResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdn_pnd_pnd_proto_msgTypes[36]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SubscribePathResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SubscribePathResponse) ProtoMessage() {}
+
+func (x *SubscribePathResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_pnd_pnd_proto_msgTypes[36]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SubscribePathResponse.ProtoReflect.Descriptor instead.
+func (*SubscribePathResponse) Descriptor() ([]byte, []int) {
+	return file_gosdn_pnd_pnd_proto_rawDescGZIP(), []int{36}
+}
+
+func (x *SubscribePathResponse) GetTimestamp() int64 {
+	if x != nil {
+		return x.Timestamp
+	}
+	return 0
+}
+
+func (x *SubscribePathResponse) GetStatus() Status {
+	if x != nil {
+		return x.Status
+	}
+	return Status_STATUS_UNSPECIFIED
+}
+
+func (x *SubscribePathResponse) GetDevice() []*gnmi.Notification {
+	if x != nil {
+		return x.Device
+	}
+	return nil
+}
+
 var File_gosdn_pnd_pnd_proto protoreflect.FileDescriptor
 
 var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
@@ -2623,142 +2981,199 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74,
 	0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
 	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
-	0x74, 0x75, 0x73, 0x2a, 0x9c, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74,
-	0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54,
-	0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-	0x00, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54,
-	0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43,
-	0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
-	0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47,
-	0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45,
-	0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54,
-	0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4e, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54,
-	0x10, 0x04, 0x2a, 0x7c, 0x0a, 0x0c, 0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54,
+	0x74, 0x75, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62,
+	0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
+	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69,
+	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03,
+	0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x35,
+	0x0a, 0x07, 0x73, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73,
+	0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x73, 0x75,
+	0x62, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x80, 0x01, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
+	0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x0c, 0x73, 0x75,
+	0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x17, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62,
+	0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63,
+	0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
+	0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f,
+	0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x83, 0x01, 0x0a, 0x0c, 0x53, 0x75, 0x62,
+	0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74,
+	0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x36, 0x0a,
+	0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0e, 0x32, 0x15, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
+	0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61,
+	0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e,
+	0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x8c,
+	0x01, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x61, 0x74, 0x68,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
+	0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
+	0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x12, 0x2a, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2a, 0x9c, 0x01,
+	0x0a, 0x0b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a,
+	0x18, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e,
+	0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x43,
+	0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44,
+	0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f,
+	0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10,
+	0x02, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54,
+	0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a,
+	0x19, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e,
+	0x43, 0x4f, 0x4e, 0x53, 0x49, 0x53, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x04, 0x2a, 0x7c, 0x0a, 0x0c,
+	0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x19,
+	0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e,
+	0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x41,
+	0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44,
+	0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45,
+	0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02,
+	0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f,
+	0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x2a, 0x6d, 0x0a, 0x07, 0x53, 0x62,
+	0x69, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50,
+	0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+	0x17, 0x0a, 0x13, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e,
+	0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x42, 0x49, 0x5f,
+	0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x49, 0x53,
+	0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45,
+	0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54,
 	0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-	0x00, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49,
-	0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x41,
-	0x50, 0x49, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x50,
-	0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x50, 0x49, 0x5f, 0x4f, 0x50,
-	0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03,
-	0x2a, 0x6d, 0x0a, 0x07, 0x53, 0x62, 0x69, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53,
-	0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
-	0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50,
-	0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1a,
-	0x0a, 0x16, 0x53, 0x42, 0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41,
-	0x49, 0x4e, 0x45, 0x52, 0x49, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x42,
-	0x49, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x03, 0x2a,
-	0x69, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15,
-	0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
-	0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41,
-	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a,
-	0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
-	0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e,
-	0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x10, 0x03, 0x2a, 0x41, 0x0a, 0x06, 0x53, 0x74,
-	0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55,
-	0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09,
-	0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53,
-	0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0xfc, 0x09,
-	0x0a, 0x0a, 0x50, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a,
-	0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73,
-	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12,
-	0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64,
-	0x73, 0x12, 0x5c, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x12, 0x18, 0x2e, 0x67, 0x6f,
+	0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43,
+	0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41,
+	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a,
+	0x11, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49,
+	0x52, 0x4d, 0x10, 0x03, 0x2a, 0x41, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16,
+	0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+	0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
+	0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f,
+	0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x8b, 0x01, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73,
+	0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x1d,
+	0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44,
+	0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+	0x1a, 0x0a, 0x16, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+	0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x53,
+	0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
+	0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x55, 0x42,
+	0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x50,
+	0x4f, 0x4c, 0x4c, 0x10, 0x03, 0x2a, 0x7c, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d,
+	0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x4f,
+	0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+	0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f,
+	0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x01,
+	0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f,
+	0x4f, 0x4e, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x53,
+	0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x41, 0x4d, 0x50, 0x4c,
+	0x45, 0x10, 0x03, 0x32, 0xd4, 0x0a, 0x0a, 0x0a, 0x50, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69,
+	0x63, 0x65, 0x12, 0x63, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74,
+	0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74,
+	0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e,
+	0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82,
+	0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69,
+	0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x5c, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4f, 0x6e,
+	0x64, 0x12, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65,
+	0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f,
 	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
-	0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f,
-	0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x12,
-	0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e,
-	0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64,
-	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f,
-	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69,
-	0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93,
-	0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69,
-	0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x63, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x62,
-	0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
-	0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
-	0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64,
-	0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x12, 0x5d, 0x0a, 0x06,
-	0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
-	0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74,
-	0x53, 0x62, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4,
-	0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d,
-	0x2f, 0x73, 0x62, 0x69, 0x73, 0x2f, 0x7b, 0x73, 0x69, 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53,
-	0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
-	0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01,
-	0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73,
-	0x62, 0x69, 0x73, 0x12, 0x6f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
-	0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
-	0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
-	0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12,
-	0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61,
-	0x6e, 0x67, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67,
-	0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65,
-	0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
-	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68,
-	0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3,
-	0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64,
-	0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x2f, 0x7b, 0x63, 0x75, 0x69, 0x64, 0x7d,
-	0x12, 0x72, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73,
-	0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65,
-	0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
-	0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22,
-	0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61,
-	0x6e, 0x67, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12,
-	0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50,
-	0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23,
-	0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73,
-	0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2f, 0x7b, 0x70, 0x61,
-	0x74, 0x68, 0x7d, 0x12, 0x6f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69,
-	0x73, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53,
-	0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65,
-	0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x70,
-	0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x70,
-	0x61, 0x74, 0x68, 0x73, 0x12, 0x66, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e,
-	0x64, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65,
-	0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c,
-	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
-	0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3,
-	0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64,
-	0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x42, 0xae, 0x02, 0x5a,
-	0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64,
-	0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70,
-	0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x92, 0x41,
-	0xfb, 0x01, 0x12, 0xf8, 0x01, 0x0a, 0x10, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72,
-	0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x4d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
-	0x6c, 0x20, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x20, 0x63,
-	0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x53, 0x44,
-	0x4e, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x49, 0x6e, 0x74,
-	0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3e, 0x0a, 0x18, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20,
-	0x4e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65,
-	0x63, 0x74, 0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65,
-	0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e,
-	0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2a, 0x50, 0x0a, 0x14, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d,
-	0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x38,
-	0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69,
-	0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61,
-	0x70, 0x69, 0x2f, 0x2d, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
-	0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x03, 0x30, 0x2e, 0x31, 0x62, 0x06, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15,
+	0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x2f,
+	0x7b, 0x64, 0x69, 0x64, 0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c,
+	0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
+	0x53, 0x65, 0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65,
+	0x74, 0x4f, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e,
+	0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x63, 0x0a,
+	0x0a, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69,
+	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64,
+	0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12,
+	0x12, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62,
+	0x69, 0x73, 0x12, 0x5d, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x12, 0x18, 0x2e, 0x67,
+	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
+	0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x62, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73,
+	0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x2f, 0x7b, 0x73, 0x69, 0x64,
+	0x7d, 0x12, 0x66, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x12,
+	0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53,
+	0x62, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e,
+	0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x62, 0x69,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b,
+	0x70, 0x69, 0x64, 0x7d, 0x2f, 0x73, 0x62, 0x69, 0x73, 0x12, 0x6f, 0x0a, 0x0d, 0x47, 0x65, 0x74,
+	0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73,
+	0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67,
+	0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82,
+	0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69,
+	0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47, 0x65,
+	0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
+	0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x70, 0x6e, 0x64,
+	0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x2f,
+	0x7b, 0x63, 0x75, 0x69, 0x64, 0x7d, 0x12, 0x72, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61,
+	0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69, 0x73,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
+	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x69,
+	0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93,
+	0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69,
+	0x64, 0x7d, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x07, 0x47, 0x65,
+	0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e,
+	0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74,
+	0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64,
+	0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x74,
+	0x68, 0x73, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x7d, 0x12, 0x6f, 0x0a, 0x0b, 0x53, 0x65, 0x74,
+	0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
+	0x2e, 0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a,
+	0x01, 0x2a, 0x22, 0x16, 0x2f, 0x70, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f,
+	0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x66, 0x0a, 0x09, 0x44, 0x65,
+	0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
+	0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x70, 0x6e, 0x64,
+	0x73, 0x2f, 0x7b, 0x70, 0x69, 0x64, 0x7d, 0x2f, 0x6f, 0x6e, 0x64, 0x73, 0x2f, 0x7b, 0x64, 0x69,
+	0x64, 0x7d, 0x12, 0x56, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50,
+	0x61, 0x74, 0x68, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64, 0x2e,
+	0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
+	0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0xae, 0x02, 0x5a, 0x2d, 0x63,
+	0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f,
+	0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f,
+	0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x92, 0x41, 0xfb, 0x01,
+	0x12, 0xf8, 0x01, 0x0a, 0x10, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f, 0x72, 0x74, 0x68,
+	0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x4d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20,
+	0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x20, 0x63, 0x6f, 0x64,
+	0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20,
+	0x6e, 0x6f, 0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72,
+	0x66, 0x61, 0x63, 0x65, 0x22, 0x3e, 0x0a, 0x18, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x20, 0x4e, 0x6f,
+	0x72, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66,
+	0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74,
+	0x2f, 0x61, 0x70, 0x69, 0x2a, 0x50, 0x0a, 0x14, 0x42, 0x53, 0x44, 0x20, 0x33, 0x2d, 0x43, 0x6c,
+	0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x68, 0x74,
+	0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68,
+	0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69,
+	0x2f, 0x2d, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x4c,
+	0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x03, 0x30, 0x2e, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
 }
 
 var (
@@ -2773,119 +3188,133 @@ func file_gosdn_pnd_pnd_proto_rawDescGZIP() []byte {
 	return file_gosdn_pnd_pnd_proto_rawDescData
 }
 
-var file_gosdn_pnd_pnd_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
-var file_gosdn_pnd_pnd_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
+var file_gosdn_pnd_pnd_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
+var file_gosdn_pnd_pnd_proto_msgTypes = make([]protoimpl.MessageInfo, 37)
 var file_gosdn_pnd_pnd_proto_goTypes = []interface{}{
 	(ChangeState)(0),                       // 0: gosdn.pnd.ChangeState
 	(ApiOperation)(0),                      // 1: gosdn.pnd.ApiOperation
 	(SbiType)(0),                           // 2: gosdn.pnd.SbiType
 	(Operation)(0),                         // 3: gosdn.pnd.Operation
 	(Status)(0),                            // 4: gosdn.pnd.Status
-	(*GetOndListRequest)(nil),              // 5: gosdn.pnd.GetOndListRequest
-	(*GetOndRequest)(nil),                  // 6: gosdn.pnd.GetOndRequest
-	(*GetSbiListRequest)(nil),              // 7: gosdn.pnd.GetSbiListRequest
-	(*GetSbiRequest)(nil),                  // 8: gosdn.pnd.GetSbiRequest
-	(*GetChangeListRequest)(nil),           // 9: gosdn.pnd.GetChangeListRequest
-	(*GetChangeRequest)(nil),               // 10: gosdn.pnd.GetChangeRequest
-	(*GetPathRequest)(nil),                 // 11: gosdn.pnd.GetPathRequest
-	(*GetOndResponse)(nil),                 // 12: gosdn.pnd.GetOndResponse
-	(*GetOndListResponse)(nil),             // 13: gosdn.pnd.GetOndListResponse
-	(*GetSbiResponse)(nil),                 // 14: gosdn.pnd.GetSbiResponse
-	(*GetSbiListResponse)(nil),             // 15: gosdn.pnd.GetSbiListResponse
-	(*GetPathResponse)(nil),                // 16: gosdn.pnd.GetPathResponse
-	(*GetChangeResponse)(nil),              // 17: gosdn.pnd.GetChangeResponse
-	(*GetChangeListResponse)(nil),          // 18: gosdn.pnd.GetChangeListResponse
-	(*PrincipalNetworkDomain)(nil),         // 19: gosdn.pnd.PrincipalNetworkDomain
-	(*OrchestratedNetworkingDevice)(nil),   // 20: gosdn.pnd.OrchestratedNetworkingDevice
-	(*Change)(nil),                         // 21: gosdn.pnd.Change
-	(*SetOndListRequest)(nil),              // 22: gosdn.pnd.SetOndListRequest
-	(*SetSbiListRequest)(nil),              // 23: gosdn.pnd.SetSbiListRequest
-	(*SetChangeListRequest)(nil),           // 24: gosdn.pnd.SetChangeListRequest
-	(*SetPathListRequest)(nil),             // 25: gosdn.pnd.SetPathListRequest
-	(*ChangeRequest)(nil),                  // 26: gosdn.pnd.ChangeRequest
-	(*SetOnd)(nil),                         // 27: gosdn.pnd.SetOnd
-	(*SetSbi)(nil),                         // 28: gosdn.pnd.SetSbi
-	(*SetChange)(nil),                      // 29: gosdn.pnd.SetChange
-	(*SetResponse)(nil),                    // 30: gosdn.pnd.SetResponse
-	(*SetOndListResponse)(nil),             // 31: gosdn.pnd.SetOndListResponse
-	(*SetChangeListResponse)(nil),          // 32: gosdn.pnd.SetChangeListResponse
-	(*SetChangeResponse)(nil),              // 33: gosdn.pnd.SetChangeResponse
-	(*SetSbiListResponse)(nil),             // 34: gosdn.pnd.SetSbiListResponse
-	(*SetPathListResponse)(nil),            // 35: gosdn.pnd.SetPathListResponse
-	(*DeleteOndRequest)(nil),               // 36: gosdn.pnd.DeleteOndRequest
-	(*DeleteOndResponse)(nil),              // 37: gosdn.pnd.DeleteOndResponse
-	(*southbound.SouthboundInterface)(nil), // 38: gosdn.southbound.SouthboundInterface
-	(*gnmi.Notification)(nil),              // 39: gnmi.Notification
-	(*transport.TransportOption)(nil),      // 40: gosdn.transport.TransportOption
+	(SubscriptionMode)(0),                  // 5: gosdn.pnd.SubscriptionMode
+	(StreamMode)(0),                        // 6: gosdn.pnd.StreamMode
+	(*GetOndListRequest)(nil),              // 7: gosdn.pnd.GetOndListRequest
+	(*GetOndRequest)(nil),                  // 8: gosdn.pnd.GetOndRequest
+	(*GetSbiListRequest)(nil),              // 9: gosdn.pnd.GetSbiListRequest
+	(*GetSbiRequest)(nil),                  // 10: gosdn.pnd.GetSbiRequest
+	(*GetChangeListRequest)(nil),           // 11: gosdn.pnd.GetChangeListRequest
+	(*GetChangeRequest)(nil),               // 12: gosdn.pnd.GetChangeRequest
+	(*GetPathRequest)(nil),                 // 13: gosdn.pnd.GetPathRequest
+	(*GetOndResponse)(nil),                 // 14: gosdn.pnd.GetOndResponse
+	(*GetOndListResponse)(nil),             // 15: gosdn.pnd.GetOndListResponse
+	(*GetSbiResponse)(nil),                 // 16: gosdn.pnd.GetSbiResponse
+	(*GetSbiListResponse)(nil),             // 17: gosdn.pnd.GetSbiListResponse
+	(*GetPathResponse)(nil),                // 18: gosdn.pnd.GetPathResponse
+	(*GetChangeResponse)(nil),              // 19: gosdn.pnd.GetChangeResponse
+	(*GetChangeListResponse)(nil),          // 20: gosdn.pnd.GetChangeListResponse
+	(*PrincipalNetworkDomain)(nil),         // 21: gosdn.pnd.PrincipalNetworkDomain
+	(*OrchestratedNetworkingDevice)(nil),   // 22: gosdn.pnd.OrchestratedNetworkingDevice
+	(*Change)(nil),                         // 23: gosdn.pnd.Change
+	(*SetOndListRequest)(nil),              // 24: gosdn.pnd.SetOndListRequest
+	(*SetSbiListRequest)(nil),              // 25: gosdn.pnd.SetSbiListRequest
+	(*SetChangeListRequest)(nil),           // 26: gosdn.pnd.SetChangeListRequest
+	(*SetPathListRequest)(nil),             // 27: gosdn.pnd.SetPathListRequest
+	(*ChangeRequest)(nil),                  // 28: gosdn.pnd.ChangeRequest
+	(*SetOnd)(nil),                         // 29: gosdn.pnd.SetOnd
+	(*SetSbi)(nil),                         // 30: gosdn.pnd.SetSbi
+	(*SetChange)(nil),                      // 31: gosdn.pnd.SetChange
+	(*SetResponse)(nil),                    // 32: gosdn.pnd.SetResponse
+	(*SetOndListResponse)(nil),             // 33: gosdn.pnd.SetOndListResponse
+	(*SetChangeListResponse)(nil),          // 34: gosdn.pnd.SetChangeListResponse
+	(*SetChangeResponse)(nil),              // 35: gosdn.pnd.SetChangeResponse
+	(*SetSbiListResponse)(nil),             // 36: gosdn.pnd.SetSbiListResponse
+	(*SetPathListResponse)(nil),            // 37: gosdn.pnd.SetPathListResponse
+	(*DeleteOndRequest)(nil),               // 38: gosdn.pnd.DeleteOndRequest
+	(*DeleteOndResponse)(nil),              // 39: gosdn.pnd.DeleteOndResponse
+	(*SubscribePathRequest)(nil),           // 40: gosdn.pnd.SubscribePathRequest
+	(*SubscriptionList)(nil),               // 41: gosdn.pnd.SubscriptionList
+	(*Subscription)(nil),                   // 42: gosdn.pnd.Subscription
+	(*SubscribePathResponse)(nil),          // 43: gosdn.pnd.SubscribePathResponse
+	(*southbound.SouthboundInterface)(nil), // 44: gosdn.southbound.SouthboundInterface
+	(*gnmi.Notification)(nil),              // 45: gnmi.Notification
+	(*transport.TransportOption)(nil),      // 46: gosdn.transport.TransportOption
 }
 var file_gosdn_pnd_pnd_proto_depIdxs = []int32{
-	19, // 0: gosdn.pnd.GetOndResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	20, // 1: gosdn.pnd.GetOndResponse.ond:type_name -> gosdn.pnd.OrchestratedNetworkingDevice
-	19, // 2: gosdn.pnd.GetOndListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	20, // 3: gosdn.pnd.GetOndListResponse.ond:type_name -> gosdn.pnd.OrchestratedNetworkingDevice
-	19, // 4: gosdn.pnd.GetSbiResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	38, // 5: gosdn.pnd.GetSbiResponse.sbi:type_name -> gosdn.southbound.SouthboundInterface
-	19, // 6: gosdn.pnd.GetSbiListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	38, // 7: gosdn.pnd.GetSbiListResponse.sbi:type_name -> gosdn.southbound.SouthboundInterface
-	19, // 8: gosdn.pnd.GetPathResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	39, // 9: gosdn.pnd.GetPathResponse.device:type_name -> gnmi.Notification
-	19, // 10: gosdn.pnd.GetChangeResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	21, // 11: gosdn.pnd.GetChangeResponse.change:type_name -> gosdn.pnd.Change
-	19, // 12: gosdn.pnd.GetChangeListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
-	21, // 13: gosdn.pnd.GetChangeListResponse.change:type_name -> gosdn.pnd.Change
-	39, // 14: gosdn.pnd.OrchestratedNetworkingDevice.device:type_name -> gnmi.Notification
-	38, // 15: gosdn.pnd.OrchestratedNetworkingDevice.sbi:type_name -> gosdn.southbound.SouthboundInterface
+	21, // 0: gosdn.pnd.GetOndResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	22, // 1: gosdn.pnd.GetOndResponse.ond:type_name -> gosdn.pnd.OrchestratedNetworkingDevice
+	21, // 2: gosdn.pnd.GetOndListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	22, // 3: gosdn.pnd.GetOndListResponse.ond:type_name -> gosdn.pnd.OrchestratedNetworkingDevice
+	21, // 4: gosdn.pnd.GetSbiResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	44, // 5: gosdn.pnd.GetSbiResponse.sbi:type_name -> gosdn.southbound.SouthboundInterface
+	21, // 6: gosdn.pnd.GetSbiListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	44, // 7: gosdn.pnd.GetSbiListResponse.sbi:type_name -> gosdn.southbound.SouthboundInterface
+	21, // 8: gosdn.pnd.GetPathResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	45, // 9: gosdn.pnd.GetPathResponse.device:type_name -> gnmi.Notification
+	21, // 10: gosdn.pnd.GetChangeResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	23, // 11: gosdn.pnd.GetChangeResponse.change:type_name -> gosdn.pnd.Change
+	21, // 12: gosdn.pnd.GetChangeListResponse.pnd:type_name -> gosdn.pnd.PrincipalNetworkDomain
+	23, // 13: gosdn.pnd.GetChangeListResponse.change:type_name -> gosdn.pnd.Change
+	45, // 14: gosdn.pnd.OrchestratedNetworkingDevice.device:type_name -> gnmi.Notification
+	44, // 15: gosdn.pnd.OrchestratedNetworkingDevice.sbi:type_name -> gosdn.southbound.SouthboundInterface
 	0,  // 16: gosdn.pnd.Change.state:type_name -> gosdn.pnd.ChangeState
-	39, // 17: gosdn.pnd.Change.diff:type_name -> gnmi.Notification
-	27, // 18: gosdn.pnd.SetOndListRequest.ond:type_name -> gosdn.pnd.SetOnd
-	28, // 19: gosdn.pnd.SetSbiListRequest.sbi:type_name -> gosdn.pnd.SetSbi
-	29, // 20: gosdn.pnd.SetChangeListRequest.change:type_name -> gosdn.pnd.SetChange
-	26, // 21: gosdn.pnd.SetPathListRequest.change_request:type_name -> gosdn.pnd.ChangeRequest
+	45, // 17: gosdn.pnd.Change.diff:type_name -> gnmi.Notification
+	29, // 18: gosdn.pnd.SetOndListRequest.ond:type_name -> gosdn.pnd.SetOnd
+	30, // 19: gosdn.pnd.SetSbiListRequest.sbi:type_name -> gosdn.pnd.SetSbi
+	31, // 20: gosdn.pnd.SetChangeListRequest.change:type_name -> gosdn.pnd.SetChange
+	28, // 21: gosdn.pnd.SetPathListRequest.change_request:type_name -> gosdn.pnd.ChangeRequest
 	1,  // 22: gosdn.pnd.ChangeRequest.api_op:type_name -> gosdn.pnd.ApiOperation
-	38, // 23: gosdn.pnd.SetOnd.sbi:type_name -> gosdn.southbound.SouthboundInterface
-	40, // 24: gosdn.pnd.SetOnd.transport_option:type_name -> gosdn.transport.TransportOption
+	44, // 23: gosdn.pnd.SetOnd.sbi:type_name -> gosdn.southbound.SouthboundInterface
+	46, // 24: gosdn.pnd.SetOnd.transport_option:type_name -> gosdn.transport.TransportOption
 	2,  // 25: gosdn.pnd.SetSbi.sbi_type:type_name -> gosdn.pnd.SbiType
 	3,  // 26: gosdn.pnd.SetChange.op:type_name -> gosdn.pnd.Operation
 	4,  // 27: gosdn.pnd.SetResponse.status:type_name -> gosdn.pnd.Status
 	4,  // 28: gosdn.pnd.SetOndListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 29: gosdn.pnd.SetOndListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	32, // 29: gosdn.pnd.SetOndListResponse.responses:type_name -> gosdn.pnd.SetResponse
 	4,  // 30: gosdn.pnd.SetChangeListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 31: gosdn.pnd.SetChangeListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	32, // 31: gosdn.pnd.SetChangeListResponse.responses:type_name -> gosdn.pnd.SetResponse
 	4,  // 32: gosdn.pnd.SetChangeResponse.status:type_name -> gosdn.pnd.Status
 	4,  // 33: gosdn.pnd.SetSbiListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 34: gosdn.pnd.SetSbiListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	32, // 34: gosdn.pnd.SetSbiListResponse.responses:type_name -> gosdn.pnd.SetResponse
 	4,  // 35: gosdn.pnd.SetPathListResponse.status:type_name -> gosdn.pnd.Status
-	30, // 36: gosdn.pnd.SetPathListResponse.responses:type_name -> gosdn.pnd.SetResponse
+	32, // 36: gosdn.pnd.SetPathListResponse.responses:type_name -> gosdn.pnd.SetResponse
 	4,  // 37: gosdn.pnd.DeleteOndResponse.status:type_name -> gosdn.pnd.Status
-	5,  // 38: gosdn.pnd.PndService.GetOndList:input_type -> gosdn.pnd.GetOndListRequest
-	6,  // 39: gosdn.pnd.PndService.GetOnd:input_type -> gosdn.pnd.GetOndRequest
-	22, // 40: gosdn.pnd.PndService.SetOndList:input_type -> gosdn.pnd.SetOndListRequest
-	7,  // 41: gosdn.pnd.PndService.GetSbiList:input_type -> gosdn.pnd.GetSbiListRequest
-	8,  // 42: gosdn.pnd.PndService.GetSbi:input_type -> gosdn.pnd.GetSbiRequest
-	23, // 43: gosdn.pnd.PndService.SetSbiList:input_type -> gosdn.pnd.SetSbiListRequest
-	9,  // 44: gosdn.pnd.PndService.GetChangeList:input_type -> gosdn.pnd.GetChangeListRequest
-	10, // 45: gosdn.pnd.PndService.GetChange:input_type -> gosdn.pnd.GetChangeRequest
-	24, // 46: gosdn.pnd.PndService.SetChangeList:input_type -> gosdn.pnd.SetChangeListRequest
-	11, // 47: gosdn.pnd.PndService.GetPath:input_type -> gosdn.pnd.GetPathRequest
-	25, // 48: gosdn.pnd.PndService.SetPathList:input_type -> gosdn.pnd.SetPathListRequest
-	36, // 49: gosdn.pnd.PndService.DeleteOnd:input_type -> gosdn.pnd.DeleteOndRequest
-	13, // 50: gosdn.pnd.PndService.GetOndList:output_type -> gosdn.pnd.GetOndListResponse
-	12, // 51: gosdn.pnd.PndService.GetOnd:output_type -> gosdn.pnd.GetOndResponse
-	31, // 52: gosdn.pnd.PndService.SetOndList:output_type -> gosdn.pnd.SetOndListResponse
-	15, // 53: gosdn.pnd.PndService.GetSbiList:output_type -> gosdn.pnd.GetSbiListResponse
-	14, // 54: gosdn.pnd.PndService.GetSbi:output_type -> gosdn.pnd.GetSbiResponse
-	34, // 55: gosdn.pnd.PndService.SetSbiList:output_type -> gosdn.pnd.SetSbiListResponse
-	18, // 56: gosdn.pnd.PndService.GetChangeList:output_type -> gosdn.pnd.GetChangeListResponse
-	17, // 57: gosdn.pnd.PndService.GetChange:output_type -> gosdn.pnd.GetChangeResponse
-	32, // 58: gosdn.pnd.PndService.SetChangeList:output_type -> gosdn.pnd.SetChangeListResponse
-	16, // 59: gosdn.pnd.PndService.GetPath:output_type -> gosdn.pnd.GetPathResponse
-	35, // 60: gosdn.pnd.PndService.SetPathList:output_type -> gosdn.pnd.SetPathListResponse
-	37, // 61: gosdn.pnd.PndService.DeleteOnd:output_type -> gosdn.pnd.DeleteOndResponse
-	50, // [50:62] is the sub-list for method output_type
-	38, // [38:50] is the sub-list for method input_type
-	38, // [38:38] is the sub-list for extension type_name
-	38, // [38:38] is the sub-list for extension extendee
-	0,  // [0:38] is the sub-list for field type_name
+	41, // 38: gosdn.pnd.SubscribePathRequest.sublist:type_name -> gosdn.pnd.SubscriptionList
+	42, // 39: gosdn.pnd.SubscriptionList.subscription:type_name -> gosdn.pnd.Subscription
+	5,  // 40: gosdn.pnd.SubscriptionList.mode:type_name -> gosdn.pnd.SubscriptionMode
+	6,  // 41: gosdn.pnd.Subscription.stream_mode:type_name -> gosdn.pnd.StreamMode
+	4,  // 42: gosdn.pnd.SubscribePathResponse.status:type_name -> gosdn.pnd.Status
+	45, // 43: gosdn.pnd.SubscribePathResponse.device:type_name -> gnmi.Notification
+	7,  // 44: gosdn.pnd.PndService.GetOndList:input_type -> gosdn.pnd.GetOndListRequest
+	8,  // 45: gosdn.pnd.PndService.GetOnd:input_type -> gosdn.pnd.GetOndRequest
+	24, // 46: gosdn.pnd.PndService.SetOndList:input_type -> gosdn.pnd.SetOndListRequest
+	9,  // 47: gosdn.pnd.PndService.GetSbiList:input_type -> gosdn.pnd.GetSbiListRequest
+	10, // 48: gosdn.pnd.PndService.GetSbi:input_type -> gosdn.pnd.GetSbiRequest
+	25, // 49: gosdn.pnd.PndService.SetSbiList:input_type -> gosdn.pnd.SetSbiListRequest
+	11, // 50: gosdn.pnd.PndService.GetChangeList:input_type -> gosdn.pnd.GetChangeListRequest
+	12, // 51: gosdn.pnd.PndService.GetChange:input_type -> gosdn.pnd.GetChangeRequest
+	26, // 52: gosdn.pnd.PndService.SetChangeList:input_type -> gosdn.pnd.SetChangeListRequest
+	13, // 53: gosdn.pnd.PndService.GetPath:input_type -> gosdn.pnd.GetPathRequest
+	27, // 54: gosdn.pnd.PndService.SetPathList:input_type -> gosdn.pnd.SetPathListRequest
+	38, // 55: gosdn.pnd.PndService.DeleteOnd:input_type -> gosdn.pnd.DeleteOndRequest
+	40, // 56: gosdn.pnd.PndService.SubscribePath:input_type -> gosdn.pnd.SubscribePathRequest
+	15, // 57: gosdn.pnd.PndService.GetOndList:output_type -> gosdn.pnd.GetOndListResponse
+	14, // 58: gosdn.pnd.PndService.GetOnd:output_type -> gosdn.pnd.GetOndResponse
+	33, // 59: gosdn.pnd.PndService.SetOndList:output_type -> gosdn.pnd.SetOndListResponse
+	17, // 60: gosdn.pnd.PndService.GetSbiList:output_type -> gosdn.pnd.GetSbiListResponse
+	16, // 61: gosdn.pnd.PndService.GetSbi:output_type -> gosdn.pnd.GetSbiResponse
+	36, // 62: gosdn.pnd.PndService.SetSbiList:output_type -> gosdn.pnd.SetSbiListResponse
+	20, // 63: gosdn.pnd.PndService.GetChangeList:output_type -> gosdn.pnd.GetChangeListResponse
+	19, // 64: gosdn.pnd.PndService.GetChange:output_type -> gosdn.pnd.GetChangeResponse
+	34, // 65: gosdn.pnd.PndService.SetChangeList:output_type -> gosdn.pnd.SetChangeListResponse
+	18, // 66: gosdn.pnd.PndService.GetPath:output_type -> gosdn.pnd.GetPathResponse
+	37, // 67: gosdn.pnd.PndService.SetPathList:output_type -> gosdn.pnd.SetPathListResponse
+	39, // 68: gosdn.pnd.PndService.DeleteOnd:output_type -> gosdn.pnd.DeleteOndResponse
+	43, // 69: gosdn.pnd.PndService.SubscribePath:output_type -> gosdn.pnd.SubscribePathResponse
+	57, // [57:70] is the sub-list for method output_type
+	44, // [44:57] is the sub-list for method input_type
+	44, // [44:44] is the sub-list for extension type_name
+	44, // [44:44] is the sub-list for extension extendee
+	0,  // [0:44] is the sub-list for field type_name
 }
 
 func init() { file_gosdn_pnd_pnd_proto_init() }
@@ -3290,14 +3719,62 @@ func file_gosdn_pnd_pnd_proto_init() {
 				return nil
 			}
 		}
+		file_gosdn_pnd_pnd_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SubscribePathRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdn_pnd_pnd_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SubscriptionList); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdn_pnd_pnd_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Subscription); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdn_pnd_pnd_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*SubscribePathResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_gosdn_pnd_pnd_proto_rawDesc,
-			NumEnums:      5,
-			NumMessages:   33,
+			NumEnums:      7,
+			NumMessages:   37,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/api/go/gosdn/pnd/pnd_grpc.pb.go b/api/go/gosdn/pnd/pnd_grpc.pb.go
index bc681280de05002ce2a8bcacb94bd30e6e03cc44..8f51b481ff262c48401f6c8a6d43472292914a51 100644
--- a/api/go/gosdn/pnd/pnd_grpc.pb.go
+++ b/api/go/gosdn/pnd/pnd_grpc.pb.go
@@ -51,6 +51,10 @@ type PndServiceClient interface {
 	// Allows to delete a specific Orchestrated Networking Device which is managed by a
 	// specific Principal Network Domain.
 	DeleteOnd(ctx context.Context, in *DeleteOndRequest, opts ...grpc.CallOption) (*DeleteOndResponse, error)
+	// Allows to subscribe to multiple paths of an Orchestrated Networking Device which is
+	// managed by a specific Principal Network Domain and streams data depending on the subscribe
+	// method.
+	SubscribePath(ctx context.Context, in *SubscribePathRequest, opts ...grpc.CallOption) (PndService_SubscribePathClient, error)
 }
 
 type pndServiceClient struct {
@@ -169,6 +173,38 @@ func (c *pndServiceClient) DeleteOnd(ctx context.Context, in *DeleteOndRequest,
 	return out, nil
 }
 
+func (c *pndServiceClient) SubscribePath(ctx context.Context, in *SubscribePathRequest, opts ...grpc.CallOption) (PndService_SubscribePathClient, error) {
+	stream, err := c.cc.NewStream(ctx, &PndService_ServiceDesc.Streams[0], "/gosdn.pnd.PndService/SubscribePath", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &pndServiceSubscribePathClient{stream}
+	if err := x.ClientStream.SendMsg(in); err != nil {
+		return nil, err
+	}
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	return x, nil
+}
+
+type PndService_SubscribePathClient interface {
+	Recv() (*SubscribePathResponse, error)
+	grpc.ClientStream
+}
+
+type pndServiceSubscribePathClient struct {
+	grpc.ClientStream
+}
+
+func (x *pndServiceSubscribePathClient) Recv() (*SubscribePathResponse, error) {
+	m := new(SubscribePathResponse)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
 // PndServiceServer is the server API for PndService service.
 // All implementations must embed UnimplementedPndServiceServer
 // for forward compatibility
@@ -206,6 +242,10 @@ type PndServiceServer interface {
 	// Allows to delete a specific Orchestrated Networking Device which is managed by a
 	// specific Principal Network Domain.
 	DeleteOnd(context.Context, *DeleteOndRequest) (*DeleteOndResponse, error)
+	// Allows to subscribe to multiple paths of an Orchestrated Networking Device which is
+	// managed by a specific Principal Network Domain and streams data depending on the subscribe
+	// method.
+	SubscribePath(*SubscribePathRequest, PndService_SubscribePathServer) error
 	mustEmbedUnimplementedPndServiceServer()
 }
 
@@ -249,6 +289,9 @@ func (UnimplementedPndServiceServer) SetPathList(context.Context, *SetPathListRe
 func (UnimplementedPndServiceServer) DeleteOnd(context.Context, *DeleteOndRequest) (*DeleteOndResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method DeleteOnd not implemented")
 }
+func (UnimplementedPndServiceServer) SubscribePath(*SubscribePathRequest, PndService_SubscribePathServer) error {
+	return status.Errorf(codes.Unimplemented, "method SubscribePath not implemented")
+}
 func (UnimplementedPndServiceServer) mustEmbedUnimplementedPndServiceServer() {}
 
 // UnsafePndServiceServer may be embedded to opt out of forward compatibility for this service.
@@ -478,6 +521,27 @@ func _PndService_DeleteOnd_Handler(srv interface{}, ctx context.Context, dec fun
 	return interceptor(ctx, in, info, handler)
 }
 
+func _PndService_SubscribePath_Handler(srv interface{}, stream grpc.ServerStream) error {
+	m := new(SubscribePathRequest)
+	if err := stream.RecvMsg(m); err != nil {
+		return err
+	}
+	return srv.(PndServiceServer).SubscribePath(m, &pndServiceSubscribePathServer{stream})
+}
+
+type PndService_SubscribePathServer interface {
+	Send(*SubscribePathResponse) error
+	grpc.ServerStream
+}
+
+type pndServiceSubscribePathServer struct {
+	grpc.ServerStream
+}
+
+func (x *pndServiceSubscribePathServer) Send(m *SubscribePathResponse) error {
+	return x.ServerStream.SendMsg(m)
+}
+
 // PndService_ServiceDesc is the grpc.ServiceDesc for PndService service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
@@ -534,6 +598,12 @@ var PndService_ServiceDesc = grpc.ServiceDesc{
 			Handler:    _PndService_DeleteOnd_Handler,
 		},
 	},
-	Streams:  []grpc.StreamDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "SubscribePath",
+			Handler:       _PndService_SubscribePath_Handler,
+			ServerStreams: true,
+		},
+	},
 	Metadata: "gosdn/pnd/pnd.proto",
 }
diff --git a/api/openapiv2/gosdn_northbound.swagger.json b/api/openapiv2/gosdn_northbound.swagger.json
index af22a6a6698f1af5938dafe014840b2d62e12995..69bed00d7edfeade732080856ea454d749ea902b 100644
--- a/api/openapiv2/gosdn_northbound.swagger.json
+++ b/api/openapiv2/gosdn_northbound.swagger.json
@@ -2892,6 +2892,46 @@
       ],
       "default": "STATUS_UNSPECIFIED"
     },
+    "gosdnpndSubscription": {
+      "type": "object",
+      "properties": {
+        "path": {
+          "type": "string"
+        },
+        "streamMode": {
+          "$ref": "#/definitions/pndStreamMode"
+        },
+        "sampleInterval": {
+          "type": "string",
+          "format": "uint64"
+        }
+      }
+    },
+    "gosdnpndSubscriptionList": {
+      "type": "object",
+      "properties": {
+        "subscription": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/gosdnpndSubscription"
+          }
+        },
+        "mode": {
+          "$ref": "#/definitions/gosdnpndSubscriptionMode"
+        }
+      },
+      "title": "The mode determines how the target should trigger updates to be sent.\nReference: gNMI Specification Section 3.5.1.2"
+    },
+    "gosdnpndSubscriptionMode": {
+      "type": "string",
+      "enum": [
+        "SUBSCRIPTION_MODE_UNSPECIFIED",
+        "SUBSCRIPTION_MODE_ONCE",
+        "SUBSCRIPTION_MODE_STREAM",
+        "SUBSCRIPTION_MODE_POLL"
+      ],
+      "default": "SUBSCRIPTION_MODE_UNSPECIFIED"
+    },
     "gosdnrbacRole": {
       "type": "object",
       "properties": {
@@ -3310,6 +3350,34 @@
         }
       }
     },
+    "pndStreamMode": {
+      "type": "string",
+      "enum": [
+        "STREAM_MODE_UNSPECIFIED",
+        "STREAM_MODE_TARGET_DEFINED",
+        "STREAM_MODE_ON_CHANGE",
+        "STREAM_MODE_SAMPLE"
+      ],
+      "default": "STREAM_MODE_UNSPECIFIED"
+    },
+    "pndSubscribePathResponse": {
+      "type": "object",
+      "properties": {
+        "timestamp": {
+          "type": "string",
+          "format": "int64"
+        },
+        "status": {
+          "$ref": "#/definitions/gosdnpndStatus"
+        },
+        "device": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/gnmiNotification"
+          }
+        }
+      }
+    },
     "protobufAny": {
       "type": "object",
       "properties": {
diff --git a/api/proto/gosdn/pnd/pnd.proto b/api/proto/gosdn/pnd/pnd.proto
index d68ef4940e68f6987808b4482fe8137136a9393f..6b3a8940f6a424395987a5f9b31a54535a712ff8 100644
--- a/api/proto/gosdn/pnd/pnd.proto
+++ b/api/proto/gosdn/pnd/pnd.proto
@@ -114,6 +114,10 @@ service PndService {
       delete: "/pnds/{pid}/onds/{did}"
     };
   }
+  // Allows to subscribe to multiple paths of an Orchestrated Networking Device which is
+  // managed by a specific Principal Network Domain and streams data depending on the subscribe
+  // method.
+  rpc SubscribePath(SubscribePathRequest) returns (stream SubscribePathResponse) {};
 }
 
 message GetOndListRequest {
@@ -360,3 +364,44 @@ enum Status {
   STATUS_OK = 1;
   STATUS_ERROR = 2;
 }
+
+message SubscribePathRequest {
+    int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
+    string did = 2;
+    string pid = 3;
+    SubscriptionList sublist = 4;
+}
+
+// The mode determines how the target should trigger updates to be sent.
+// Reference: gNMI Specification Section 3.5.1.2
+message SubscriptionList {
+    repeated Subscription subscription = 1;
+    SubscriptionMode mode = 2;
+}
+
+enum SubscriptionMode {
+    SUBSCRIPTION_MODE_UNSPECIFIED = 0;
+    SUBSCRIPTION_MODE_ONCE = 1;
+    SUBSCRIPTION_MODE_STREAM = 2;
+    SUBSCRIPTION_MODE_POLL = 3;
+}
+
+message Subscription {
+    string path = 1;
+    StreamMode stream_mode = 2;
+    uint64 sample_interval = 3;       // ns between samples in SAMPLE mode.
+}
+
+enum StreamMode {
+    STREAM_MODE_UNSPECIFIED = 0;
+    STREAM_MODE_TARGET_DEFINED = 1;  // The target selects the relevant mode for each element.
+    STREAM_MODE_ON_CHANGE      = 2;  // The target sends an update on element value change.
+    STREAM_MODE_SAMPLE         = 3; // The target samples values according to the interval.
+}
+
+
+message SubscribePathResponse {
+    int64 timestamp = 1;          // Timestamp in nanoseconds since Epoch.
+    Status status = 2;
+    repeated gnmi.Notification device = 3;
+}
diff --git a/cli/adapter/PndAdapter.go b/cli/adapter/PndAdapter.go
index a02ac56ea36adfc4f457dd03484b76fbf1d8e8fa..9d39456be20e8676541b5e15943bc32508f702f9 100644
--- a/cli/adapter/PndAdapter.go
+++ b/cli/adapter/PndAdapter.go
@@ -127,6 +127,16 @@ func (p *PndAdapter) Request(ctx context.Context, did uuid.UUID, path string) (*
 	return resp, nil
 }
 
+// SubscribeONDPath sends an API call to the controller requesting to subscribe
+// to a specific path of a specifc device
+func (p *PndAdapter) SubscribeONDPath(ctx context.Context, did uuid.UUID, slist *ppb.SubscriptionList) (ppb.PndService_SubscribePathClient, error) {
+	resp, err := api.SubscribePath(ctx, p.endpoint, p.id.String(), did.String(), slist)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
 // RequestAll sends an API call to the controller requesting the specified path
 // for all registered devices. Not yet implemented.
 func (p *PndAdapter) RequestAll(ctx context.Context, path string) ([]proto.Message, error) {
diff --git a/cli/cmd/deviceSubscribe.go b/cli/cmd/deviceSubscribe.go
new file mode 100644
index 0000000000000000000000000000000000000000..e3718790bf9d233ca9389048ae629148b785d4ac
--- /dev/null
+++ b/cli/cmd/deviceSubscribe.go
@@ -0,0 +1,103 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"io"
+
+	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
+	"github.com/google/uuid"
+	"github.com/pterm/pterm"
+	log "github.com/sirupsen/logrus"
+	"github.com/spf13/cobra"
+)
+
+// deviceGetCmd represents the get command
+var deviceSubscribeCmd = &cobra.Command{
+	Use:   "subscribe [uuid] [path]",
+	Args:  cobra.ExactArgs(2),
+	Short: "Subscribes to paths of a provided device with fixed subscribe options",
+	Long: `Requests a subscription on paths from a specified orchestrated network device on the controller.
+The device UUID and requested paths must be specified as a positional arguments.`,
+
+	RunE: func(cmd *cobra.Command, args []string) error {
+		did, err := uuid.Parse(args[0])
+		if err != nil {
+			pterm.Error.Println(err)
+			return err
+		}
+
+		subClient, err := pndAdapter.SubscribeONDPath(
+			createContextWithAuthorization(),
+			did,
+			&pnd.SubscriptionList{
+				Subscription: []*pnd.Subscription{
+					{
+						Path:           args[1],
+						StreamMode:     pnd.StreamMode_STREAM_MODE_SAMPLE,
+						SampleInterval: 1000000000,
+					},
+				},
+				Mode: pnd.SubscriptionMode_SUBSCRIPTION_MODE_STREAM,
+			},
+		)
+		if err != nil {
+			pterm.Error.Println(err)
+			return err
+		}
+
+		for i := 0; i < 5; i++ {
+			subscribeResponse, err := subClient.Recv()
+			if err != nil {
+				if err != nil {
+					if err == io.EOF {
+						break
+					}
+					log.Error(err)
+
+					closeErr := subClient.CloseSend()
+					if closeErr != nil {
+						log.Error(err)
+					}
+				}
+			}
+
+			pterm.Println(subscribeResponse.String())
+		}
+
+		return nil
+	},
+}
+
+func init() {
+	deviceCmd.AddCommand(deviceSubscribeCmd)
+}
diff --git a/controller/api/device.go b/controller/api/device.go
index 22f51cf7d71e4330fa9c4e061f19b74083dbdd44..35f211724d87cef0111344c9bc116196643b869e 100644
--- a/controller/api/device.go
+++ b/controller/api/device.go
@@ -152,6 +152,24 @@ func GetPath(ctx context.Context, addr, pid, did, path string) (*ppb.GetPathResp
 	return pndClient.GetPath(ctx, req)
 }
 
+// SubscribePath subscribes to paths on a device
+func SubscribePath(ctx context.Context, addr, pid, did string, slist *ppb.SubscriptionList) (ppb.PndService_SubscribePathClient, error) {
+	log.Println("subscribePath called")
+	pndClient, err := nbi.PndClient(addr, dialOptions...)
+	if err != nil {
+		return nil, err
+	}
+
+	req := &ppb.SubscribePathRequest{
+		Timestamp: time.Now().UnixNano(),
+		Did:       did,
+		Pid:       pid,
+		Sublist:   slist,
+	}
+
+	return pndClient.SubscribePath(ctx, req)
+}
+
 // DeleteDevice deletes a device
 func DeleteDevice(ctx context.Context, addr, pid, did string) (*ppb.DeleteOndResponse, error) {
 	pndClient, err := nbi.PndClient(addr, dialOptions...)
diff --git a/controller/controller.go b/controller/controller.go
index 923ded438b508ecbede74717f0df556b82f5ad55..7b48477b18b757da291167d04e19711e7ba9b9af 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -59,6 +59,7 @@ type Core struct {
 	grpcServer      *grpc.Server
 	nbi             *nbi.NorthboundInterface
 	eventService    eventInterfaces.Service
+	deviceWatcher   *nucleus.DeviceWatcher
 	stopChan        chan os.Signal
 
 	csbiClient cpb.CsbiServiceClient
@@ -105,6 +106,10 @@ func initialize() error {
 		return err
 	}
 
+	c.deviceWatcher = nucleus.NewDeviceWatcher(c.pndStore)
+	// TODO: udpate with actual paths to subscribe to using template/config
+	c.deviceWatcher.SubToDevices([][]string{{"system", "config", "hostname"}}, nil)
+
 	err = ensureDefaultRoleExists()
 	if err != nil {
 		return err
@@ -242,6 +247,7 @@ func ensureDefaultRoleExists() error {
 			"/gosdn.pnd.PndService/SetPathList",
 			"/gosdn.pnd.PndService/SetSbiList",
 			"/gosdn.pnd.PndService/DeleteOnd",
+			"/gosdn.pnd.PndService/SubscribePath",
 			"/gosdn.southbound.SbiService/GetSchema",
 		}))
 		if err != nil {
diff --git a/controller/eventService/Service.go b/controller/eventService/Service.go
index 5c13102d4926f0246cf2c250fe009fa72de3ca9b..c4d00cc9cf3ab4376c8906cb29e18d18227df018 100644
--- a/controller/eventService/Service.go
+++ b/controller/eventService/Service.go
@@ -10,6 +10,7 @@ import (
 	interfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/event"
 
 	amqp "github.com/rabbitmq/amqp091-go"
+	log "github.com/sirupsen/logrus"
 )
 
 // EventService is used to setup a connection to a broker and publish events to topics.
@@ -78,5 +79,7 @@ func (e *EventService) PublishEvent(topic string, event event.Event) error {
 
 // CloseConnection closes an exisiting connection.
 func (e *EventService) CloseConnection() {
-	e.connection.Close()
+	if err := e.connection.Close(); err != nil {
+		log.Error(err)
+	}
 }
diff --git a/controller/interfaces/networkdomain/pnd.go b/controller/interfaces/networkdomain/pnd.go
index ed2c7f1079605f0327e84b530deee5a37e443349..750cd46ff1f4b0684c84fe91486618e35daad3a9 100644
--- a/controller/interfaces/networkdomain/pnd.go
+++ b/controller/interfaces/networkdomain/pnd.go
@@ -35,4 +35,6 @@ type NetworkDomain interface {
 	GetChange(uuid.UUID) (change.Change, error)
 	Commit(uuid.UUID) error
 	Confirm(uuid.UUID) error
+	SubscribePath(uuid.UUID, *ppb.SubscriptionList) error
+	UpdateDeviceAfterSubscribeResponse(device.Device) error
 }
diff --git a/controller/interfaces/transport/transport.go b/controller/interfaces/transport/transport.go
index 8e32f357fff138ccc8c8248625951779efa41e5a..2822639fad82fee21a03ecde9e50ed147062694c 100644
--- a/controller/interfaces/transport/transport.go
+++ b/controller/interfaces/transport/transport.go
@@ -16,6 +16,24 @@ type Transport interface {
 	Set(ctx context.Context, payload change.Payload, path string, schema *ytypes.Schema) error
 	CustomSet(ctx context.Context, req *gpb.SetRequest) (*gpb.SetResponse, error)
 	Subscribe(ctx context.Context, params ...string) error
+	ControlPlaneSubscribe(ctx context.Context, subscribeCallbackFunc HandleSubscribeResponse,
+		subscriptionInfo *SubscriptionInformation) error
 	Type() string
 	ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error
+	ProcessControlPlaneSubscribeResponse(resp *gpb.SubscribeResponse_Update, root any, schema *ytypes.Schema) error
+}
+
+type (
+	// HandleSubscribeResponse is the callback function to handle subcription responses
+	HandleSubscribeResponse func(*gpb.SubscribeResponse, *SubscriptionInformation)
+)
+
+// SubscriptionInformation contains additional information used for internal subscriptions
+// for distinguishing from which device the information is from, to stop subscriptions and
+// error handling
+type SubscriptionInformation struct {
+	PndID       string
+	DeviceID    string
+	DeviceName  string
+	StopContext context.Context
 }
diff --git a/controller/mocks/HandleSubscribeResponse.go b/controller/mocks/HandleSubscribeResponse.go
new file mode 100644
index 0000000000000000000000000000000000000000..07d3feeda850107c25b8b08f6eef12d20d3c7a02
--- /dev/null
+++ b/controller/mocks/HandleSubscribeResponse.go
@@ -0,0 +1,35 @@
+// Code generated by mockery v2.14.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	gnmi "github.com/openconfig/gnmi/proto/gnmi"
+	mock "github.com/stretchr/testify/mock"
+
+	transport "code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport"
+)
+
+// HandleSubscribeResponse is an autogenerated mock type for the HandleSubscribeResponse type
+type HandleSubscribeResponse struct {
+	mock.Mock
+}
+
+// Execute provides a mock function with given fields: _a0, _a1
+func (_m *HandleSubscribeResponse) Execute(_a0 *gnmi.SubscribeResponse, _a1 *transport.SubscriptionInformation) {
+	_m.Called(_a0, _a1)
+}
+
+type mockConstructorTestingTNewHandleSubscribeResponse interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewHandleSubscribeResponse creates a new instance of HandleSubscribeResponse. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewHandleSubscribeResponse(t mockConstructorTestingTNewHandleSubscribeResponse) *HandleSubscribeResponse {
+	mock := &HandleSubscribeResponse{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/controller/mocks/NetworkDomain.go b/controller/mocks/NetworkDomain.go
index 2455cbb107a8c16361a9d004ddd51b845062d193..c4c289f1abcaed9dfbbc263fbc46a095394f445e 100644
--- a/controller/mocks/NetworkDomain.go
+++ b/controller/mocks/NetworkDomain.go
@@ -403,6 +403,20 @@ func (_m *NetworkDomain) RequestAll(_a0 string) error {
 	return r0
 }
 
+// SubscribePath provides a mock function with given fields: _a0, _a1
+func (_m *NetworkDomain) SubscribePath(_a0 uuid.UUID, _a1 *pnd.SubscriptionList) error {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(uuid.UUID, *pnd.SubscriptionList) error); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
 // UpdateDevice provides a mock function with given fields: _a0, _a1
 func (_m *NetworkDomain) UpdateDevice(_a0 device.Device, _a1 string) error {
 	ret := _m.Called(_a0, _a1)
@@ -417,6 +431,20 @@ func (_m *NetworkDomain) UpdateDevice(_a0 device.Device, _a1 string) error {
 	return r0
 }
 
+// UpdateDeviceAfterSubscribeResponse provides a mock function with given fields: _a0
+func (_m *NetworkDomain) UpdateDeviceAfterSubscribeResponse(_a0 device.Device) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(device.Device) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
 type mockConstructorTestingTNewNetworkDomain interface {
 	mock.TestingT
 	Cleanup(func())
diff --git a/controller/mocks/Store.go b/controller/mocks/Store.go
index 6ce0fd98513a962eeea46f362bd24474bcdc99db..f8f71cd7da2b2719058248e965e8a591a1d3f764 100644
--- a/controller/mocks/Store.go
+++ b/controller/mocks/Store.go
@@ -3,8 +3,8 @@
 package mocks
 
 import (
-	store "code.fbi.h-da.de/danet/gosdn/controller/interfaces/store"
-	uuid "github.com/google/uuid"
+	southbound "code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
+	store "code.fbi.h-da.de/danet/gosdn/controller/store"
 	mock "github.com/stretchr/testify/mock"
 )
 
@@ -13,13 +13,13 @@ type Store struct {
 	mock.Mock
 }
 
-// Add provides a mock function with given fields: item
-func (_m *Store) Add(item store.Storable) error {
-	ret := _m.Called(item)
+// Add provides a mock function with given fields: _a0
+func (_m *Store) Add(_a0 southbound.SouthboundInterface) error {
+	ret := _m.Called(_a0)
 
 	var r0 error
-	if rf, ok := ret.Get(0).(func(store.Storable) error); ok {
-		r0 = rf(item)
+	if rf, ok := ret.Get(0).(func(southbound.SouthboundInterface) error); ok {
+		r0 = rf(_a0)
 	} else {
 		r0 = ret.Error(0)
 	}
@@ -27,13 +27,13 @@ func (_m *Store) Add(item store.Storable) error {
 	return r0
 }
 
-// Delete provides a mock function with given fields: id
-func (_m *Store) Delete(id uuid.UUID) error {
-	ret := _m.Called(id)
+// Delete provides a mock function with given fields: _a0
+func (_m *Store) Delete(_a0 southbound.SouthboundInterface) error {
+	ret := _m.Called(_a0)
 
 	var r0 error
-	if rf, ok := ret.Get(0).(func(uuid.UUID) error); ok {
-		r0 = rf(id)
+	if rf, ok := ret.Get(0).(func(southbound.SouthboundInterface) error); ok {
+		r0 = rf(_a0)
 	} else {
 		r0 = ret.Error(0)
 	}
@@ -41,36 +41,20 @@ func (_m *Store) Delete(id uuid.UUID) error {
 	return r0
 }
 
-// Exists provides a mock function with given fields: id
-func (_m *Store) Exists(id uuid.UUID) bool {
-	ret := _m.Called(id)
+// Get provides a mock function with given fields: _a0
+func (_m *Store) Get(_a0 store.Query) (southbound.LoadedSbi, error) {
+	ret := _m.Called(_a0)
 
-	var r0 bool
-	if rf, ok := ret.Get(0).(func(uuid.UUID) bool); ok {
-		r0 = rf(id)
+	var r0 southbound.LoadedSbi
+	if rf, ok := ret.Get(0).(func(store.Query) southbound.LoadedSbi); ok {
+		r0 = rf(_a0)
 	} else {
-		r0 = ret.Get(0).(bool)
-	}
-
-	return r0
-}
-
-// Get provides a mock function with given fields: id
-func (_m *Store) Get(id uuid.UUID) (store.Storable, error) {
-	ret := _m.Called(id)
-
-	var r0 store.Storable
-	if rf, ok := ret.Get(0).(func(uuid.UUID) store.Storable); ok {
-		r0 = rf(id)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(store.Storable)
-		}
+		r0 = ret.Get(0).(southbound.LoadedSbi)
 	}
 
 	var r1 error
-	if rf, ok := ret.Get(1).(func(uuid.UUID) error); ok {
-		r1 = rf(id)
+	if rf, ok := ret.Get(1).(func(store.Query) error); ok {
+		r1 = rf(_a0)
 	} else {
 		r1 = ret.Error(1)
 	}
@@ -78,20 +62,27 @@ func (_m *Store) Get(id uuid.UUID) (store.Storable, error) {
 	return r0, r1
 }
 
-// UUIDs provides a mock function with given fields:
-func (_m *Store) UUIDs() []uuid.UUID {
+// GetAll provides a mock function with given fields:
+func (_m *Store) GetAll() ([]southbound.LoadedSbi, error) {
 	ret := _m.Called()
 
-	var r0 []uuid.UUID
-	if rf, ok := ret.Get(0).(func() []uuid.UUID); ok {
+	var r0 []southbound.LoadedSbi
+	if rf, ok := ret.Get(0).(func() []southbound.LoadedSbi); ok {
 		r0 = rf()
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).([]uuid.UUID)
+			r0 = ret.Get(0).([]southbound.LoadedSbi)
 		}
 	}
 
-	return r0
+	var r1 error
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
 }
 
 type mockConstructorTestingTNewStore interface {
diff --git a/controller/mocks/Transport.go b/controller/mocks/Transport.go
index 6062bf4c5a646c79782bfb0d0a16feca25ebfa3e..d6961a3fb977757487dd33ffcdbcfe71c9c420d5 100644
--- a/controller/mocks/Transport.go
+++ b/controller/mocks/Transport.go
@@ -11,6 +11,8 @@ import (
 
 	mock "github.com/stretchr/testify/mock"
 
+	transport "code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport"
+
 	ytypes "github.com/openconfig/ygot/ytypes"
 )
 
@@ -19,6 +21,20 @@ type Transport struct {
 	mock.Mock
 }
 
+// ControlPlaneSubscribe provides a mock function with given fields: ctx, subscribeCallbackFunc, subscriptionInfo
+func (_m *Transport) ControlPlaneSubscribe(ctx context.Context, subscribeCallbackFunc transport.HandleSubscribeResponse, subscriptionInfo *transport.SubscriptionInformation) error {
+	ret := _m.Called(ctx, subscribeCallbackFunc, subscriptionInfo)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context, transport.HandleSubscribeResponse, *transport.SubscriptionInformation) error); ok {
+		r0 = rf(ctx, subscribeCallbackFunc, subscriptionInfo)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
 // CustomSet provides a mock function with given fields: ctx, req
 func (_m *Transport) CustomSet(ctx context.Context, req *gnmi.SetRequest) (*gnmi.SetResponse, error) {
 	ret := _m.Called(ctx, req)
@@ -72,6 +88,20 @@ func (_m *Transport) Get(ctx context.Context, params ...string) (interface{}, er
 	return r0, r1
 }
 
+// ProcessControlPlaneSubscribeResponse provides a mock function with given fields: resp, root, schema
+func (_m *Transport) ProcessControlPlaneSubscribeResponse(resp *gnmi.SubscribeResponse_Update, root interface{}, schema *ytypes.Schema) error {
+	ret := _m.Called(resp, root, schema)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(*gnmi.SubscribeResponse_Update, interface{}, *ytypes.Schema) error); ok {
+		r0 = rf(resp, root, schema)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
 // ProcessResponse provides a mock function with given fields: resp, root, models
 func (_m *Transport) ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error {
 	ret := _m.Called(resp, root, models)
diff --git a/controller/northbound/server/pnd.go b/controller/northbound/server/pnd.go
index 5124730e44bda354d81c0433a395783a5221b462..7b88166d9bf5379bdb4fc03f60b2dc7ffcce7200 100644
--- a/controller/northbound/server/pnd.go
+++ b/controller/northbound/server/pnd.go
@@ -652,3 +652,27 @@ func (p PndServer) DeleteOnd(ctx context.Context, request *ppb.DeleteOndRequest)
 		Status:    ppb.Status_STATUS_OK,
 	}, nil
 }
+
+// SubscribePath subscribes to specifc paths of an ond
+func (p PndServer) SubscribePath(request *ppb.SubscribePathRequest, stream ppb.PndService_SubscribePathServer) error {
+	pid, err := uuid.Parse(request.Pid)
+	if err != nil {
+		return err
+	}
+
+	pnd, err := p.pndStore.Get(store.Query{ID: pid})
+	if err != nil {
+		return err
+	}
+
+	did, err := uuid.Parse(request.Did)
+	if err != nil {
+		return err
+	}
+
+	if err := pnd.SubscribePath(did, request.Sublist); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/controller/nucleus/deviceWatcher.go b/controller/nucleus/deviceWatcher.go
new file mode 100644
index 0000000000000000000000000000000000000000..de7f135afb62ca2fab0f69d823985acd3e246b38
--- /dev/null
+++ b/controller/nucleus/deviceWatcher.go
@@ -0,0 +1,168 @@
+package nucleus
+
+import (
+	"context"
+	"fmt"
+
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
+	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport"
+	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
+	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/types"
+	"code.fbi.h-da.de/danet/gosdn/controller/store"
+	"code.fbi.h-da.de/danet/gosdn/forks/goarista/gnmi"
+	"github.com/google/uuid"
+	gpb "github.com/openconfig/gnmi/proto/gnmi"
+	log "github.com/sirupsen/logrus"
+)
+
+const (
+	subscribeSampleInterval uint64 = 1000000000 // 1 second in nanoseconds
+	// TODO: These gNMI options are adjusted to arista gNMI fork. Change when switching to native gNMI.
+	gNMISubscribeMode string = "stream"
+	gNMIStreamMode    string = "on_change"
+)
+
+// DeviceWatcher is a component that subscribes to devices via gNMI from within the controller and handles
+// responses by triggering the internal event process.
+type DeviceWatcher struct {
+	pndStore           networkdomain.PndStore
+	deviceSubcriptions map[uuid.UUID]*deviceSubscriptionHelper
+}
+
+// deviceSubscriptionHelper is used to store information to stop a running subscribe go routine.
+type deviceSubscriptionHelper struct {
+	stopSubscribeCtx context.Context
+	stopFunc         context.CancelFunc
+}
+
+// NewDeviceWatcher takes a pndStore to subscribe to device paths.
+func NewDeviceWatcher(pndStore networkdomain.PndStore) *DeviceWatcher {
+	return &DeviceWatcher{
+		pndStore:           pndStore,
+		deviceSubcriptions: make(map[uuid.UUID]*deviceSubscriptionHelper),
+	}
+}
+
+// SubToDevices subscribes to every available device in each network domain according to provided SubscribeOptions.
+// Paths should be provided in the following format [][]string{{"system", "config", "hostname"}}
+// SubscribeOptions can be nil. Use nil for a fixed, pre-defined set of gNMI subscription options (streaming in sample mode each second).
+func (d *DeviceWatcher) SubToDevices(paths [][]string, opts *gnmi.SubscribeOptions) {
+	if opts == nil {
+		opts = &gnmi.SubscribeOptions{
+			Mode:           gNMISubscribeMode,
+			StreamMode:     gNMIStreamMode,
+			Paths:          paths,
+			SampleInterval: subscribeSampleInterval,
+		}
+	}
+
+	pnds, err := d.pndStore.GetAll()
+	if err != nil {
+		log.Error(err)
+	}
+
+	for _, pnd := range pnds {
+		d.subscribeToPndDevices(pnd.ID().String(), pnd, opts)
+	}
+}
+
+func (d *DeviceWatcher) subscribeToPndDevices(pndID string, pnd networkdomain.NetworkDomain, opts *gnmi.SubscribeOptions) {
+	for _, device := range pnd.Devices() {
+		subID := uuid.New()
+
+		stopContext, cancel := context.WithCancel(context.Background())
+		d.addToDeviceSubscriptions(subID, &deviceSubscriptionHelper{
+			stopSubscribeCtx: stopContext,
+			stopFunc:         cancel,
+		})
+		go d.callSubscribe(stopContext, pndID, device, opts)
+	}
+}
+
+func (d *DeviceWatcher) callSubscribe(stopContext context.Context, pndID string, device device.Device, opts *gnmi.SubscribeOptions) {
+	gNMIOptionsCtx := context.Background()
+	gNMIOptionsCtx = context.WithValue(gNMIOptionsCtx, types.CtxKeyOpts, opts)
+
+	// SubscriptionInformation contains pnd ID, device ID and name to be used in the internal subscribe to check
+	// from which device a response was sent
+	if err := device.Transport().ControlPlaneSubscribe(gNMIOptionsCtx, d.handleSubscribeResponse, &transport.SubscriptionInformation{
+		PndID:       pndID,
+		DeviceID:    device.ID().String(),
+		DeviceName:  device.Name(),
+		StopContext: stopContext,
+	}); err != nil {
+		log.Error(err)
+	}
+}
+
+func (d *DeviceWatcher) addToDeviceSubscriptions(subID uuid.UUID, devSub *deviceSubscriptionHelper) {
+	//TODO: improve handling of subscriptions, like be able to expose to apps so specific subscriptions instead of only all can be stopped in the future
+	d.deviceSubcriptions[subID] = devSub
+}
+
+// StopAndRemoveAllDeviceSubscriptions stops and removes all the available running subscriptions.
+func (d *DeviceWatcher) StopAndRemoveAllDeviceSubscriptions() {
+	for key := range d.deviceSubcriptions {
+		d.StopAndRemoveDeviceSubscription(key)
+	}
+}
+
+// StopAndRemoveDeviceSubscription passes a subscription uuid to stop the running subscription go routing and removes the entry from the map
+// of device subscriptions.
+func (d *DeviceWatcher) StopAndRemoveDeviceSubscription(subID uuid.UUID) {
+	d.deviceSubcriptions[subID].stopFunc()
+	delete(d.deviceSubcriptions, subID)
+}
+
+// handleSubscribeResponse takes the subscribe response and additional information about the device to distinguish
+// from which device a subscribe response was sent including improved error handling
+func (d *DeviceWatcher) handleSubscribeResponse(resp *gpb.SubscribeResponse, subscriptionInfo *transport.SubscriptionInformation) {
+	switch resp := resp.Response.(type) {
+	case *gpb.SubscribeResponse_Error:
+		log.Error(&errors.ErrSubscribeResponse{
+			PndID:      subscriptionInfo.PndID,
+			DeviceID:   subscriptionInfo.DeviceID,
+			DeviceName: subscriptionInfo.DeviceName,
+			Err:        fmt.Sprintf("SubscribeResponse_Error"),
+		})
+	case *gpb.SubscribeResponse_SyncResponse:
+		if !resp.SyncResponse {
+			log.Error(&errors.ErrSubscribeSyncResponse{
+				PndID:      subscriptionInfo.PndID,
+				DeviceID:   subscriptionInfo.DeviceID,
+				DeviceName: subscriptionInfo.DeviceName,
+			})
+		}
+	case *gpb.SubscribeResponse_Update:
+		d.handleSubscribeResponseUpdate(resp, subscriptionInfo)
+	default:
+		log.Infof("Invalid SubscribeResponse, %v", resp)
+	}
+}
+
+func (d *DeviceWatcher) handleSubscribeResponseUpdate(resp *gpb.SubscribeResponse_Update, subscriptionInfo *transport.SubscriptionInformation) {
+	pndID, err := uuid.Parse(subscriptionInfo.PndID)
+	if err != nil {
+		log.Error(err)
+	}
+
+	pnd, err := d.pndStore.Get(store.Query{ID: pndID})
+	if err != nil {
+		log.Error(err)
+	}
+
+	device, err := pnd.GetDevice(subscriptionInfo.DeviceID)
+	if err != nil {
+		log.Error(err)
+	}
+
+	err = device.Transport().ProcessControlPlaneSubscribeResponse(resp, device.GetModel(), device.SBI().Schema())
+	if err != nil {
+		log.Error(err)
+	} else {
+		if err := pnd.UpdateDeviceAfterSubscribeResponse(device); err != nil {
+			log.Error(err)
+		}
+	}
+}
diff --git a/controller/nucleus/errors/errors.go b/controller/nucleus/errors/errors.go
index d155b6950024a187d6b97a467c3f282acc627de0..254cb165389ff596a289d04981c8fefc799aa2f9 100644
--- a/controller/nucleus/errors/errors.go
+++ b/controller/nucleus/errors/errors.go
@@ -251,3 +251,28 @@ type ErrAMQPMessageFail struct {
 func (e ErrAMQPMessageFail) Error() string {
 	return fmt.Sprintf("Action: %s, Internal error: %v", e.Action, e.Err)
 }
+
+// ErrSubscribeResponse implements the Error interface and is called if there is an issue during a ongoing
+// gNMI Subscription.
+type ErrSubscribeResponse struct {
+	PndID      string
+	DeviceID   string
+	DeviceName string
+	Err        string
+}
+
+func (e ErrSubscribeResponse) Error() string {
+	return fmt.Sprintf("Subscribe failed, PndID: %s, DeviceID: %s, DeviceName: %s, Internal error: %s", e.PndID, e.DeviceID, e.DeviceName, e.Err)
+}
+
+// ErrSubscribeSyncResponse implements the Error interface and is called if there is an issue syncing a
+// gNMI Subscription.
+type ErrSubscribeSyncResponse struct {
+	PndID      string
+	DeviceID   string
+	DeviceName string
+}
+
+func (e ErrSubscribeSyncResponse) Error() string {
+	return fmt.Sprintf("Sync failed, PndID: %s, DeviceID: %s, DeviceName: %s", e.PndID, e.DeviceID, e.DeviceName)
+}
diff --git a/controller/nucleus/gnmi_transport.go b/controller/nucleus/gnmi_transport.go
index 5e5b94a990ad974fe36ce74dd9d1768bc004359e..029c33fa15681c318156187127cce98dd6b134a6 100644
--- a/controller/nucleus/gnmi_transport.go
+++ b/controller/nucleus/gnmi_transport.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/change"
+	tpInterface "code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport"
 
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 
@@ -202,6 +203,16 @@ func (g *Gnmi) Subscribe(ctx context.Context, params ...string) error {
 	return g.subscribe(ctx)
 }
 
+// ControlPlaneSubscribe is used to subscribe to devices from within the controller. gNMI SubscribeOptions need to be provided in the context,
+// the callback function handles the responses received from the subscription.
+func (g *Gnmi) ControlPlaneSubscribe(ctx context.Context, subscribeCallbackFunc tpInterface.HandleSubscribeResponse, subscriptionInfo *tpInterface.SubscriptionInformation) error {
+	if g.client == nil {
+		return &errors.ErrNilClient{}
+	}
+
+	return g.controlPlaneSubscribe(ctx, subscribeCallbackFunc, subscriptionInfo)
+}
+
 // Type returns the gNMI transport type
 func (g *Gnmi) Type() string {
 	return "gnmi"
@@ -226,36 +237,103 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
 		}
 	}
 	rn := r.Notification
-	errs := make([]error, 0)
 	for _, msg := range rn {
-		for _, update := range msg.Update {
-			path := update.Path
-			switch val := update.Val.Value.(type) {
-			case *gpb.TypedValue_JsonVal:
-				opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
-				if err := g.Unmarshal(val.JsonVal, path, d, opts...); err != nil {
-					errs = append(errs, err)
-				}
-			case *gpb.TypedValue_JsonIetfVal:
-				opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
-				if err := g.Unmarshal(val.JsonIetfVal, path, d, opts...); err != nil {
-					errs = append(errs, err)
-				}
-			default:
-				schema := s.RootSchema()
-				opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
-				if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil {
-					errs = append(errs, err)
-				}
+		if err := g.processResponseUpdates(msg.Update, d, root.(ygot.ValidatedGoStruct), s); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// ProcessControlPlaneSubscribeResponse processes the gNMI notification within the subscribe response, updating the provided device model.
+func (g *Gnmi) ProcessControlPlaneSubscribeResponse(resp *gpb.SubscribeResponse_Update, root any, schema *ytypes.Schema) error {
+	dModel, ok := root.(ygot.ValidatedGoStruct)
+	if !ok {
+		return &errors.ErrInvalidTypeAssertion{
+			Value: root,
+			Type:  (*ygot.ValidatedGoStruct)(nil),
+		}
+	}
+
+	notification := resp.Update
+
+	if len(notification.Update) > 0 {
+		if err := g.processResponseUpdates(notification.Update, dModel, root.(ygot.ValidatedGoStruct), schema); err != nil {
+			return err
+		}
+	}
+
+	if len(notification.Delete) > 0 {
+		if err := g.processResponseDeletes(notification.Delete, dModel, schema); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (g *Gnmi) processResponseUpdates(updates []*gpb.Update, deviceModel ygot.ValidatedGoStruct, root ygot.ValidatedGoStruct, s *ytypes.Schema) error {
+	errs := make([]error, 0)
+
+	for _, update := range updates {
+		path := update.Path
+		switch val := update.Val.Value.(type) {
+		case *gpb.TypedValue_JsonVal:
+			opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
+			if err := g.Unmarshal(val.JsonVal, path, deviceModel, opts...); err != nil {
+				errs = append(errs, err)
+			}
+		case *gpb.TypedValue_JsonIetfVal:
+			opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
+			if err := g.Unmarshal(val.JsonIetfVal, path, deviceModel, opts...); err != nil {
+				errs = append(errs, err)
+			}
+		default:
+			schema := s.RootSchema()
+			opts := []ytypes.SetNodeOpt{&ytypes.InitMissingElements{}, &ytypes.TolerateJSONInconsistencies{}}
+			if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil {
+				errs = append(errs, err)
 			}
 		}
 	}
+
+	if len(errs) != 0 {
+		return handleProcessResponseErrors(errs)
+	}
+
+	return nil
+}
+
+func handleProcessResponseErrors(errs []error) error {
 	for _, e := range errs {
 		log.Error(e)
 	}
-	if len(errs) != 0 {
-		return fmt.Errorf("encountered %v errors during response processing\n%v", len(errs), errs)
+
+	return fmt.Errorf("encountered %v errors during response processing\n%v", len(errs), errs)
+}
+
+func (g *Gnmi) processResponseDeletes(deletes []*gpb.Path, deviceModel ygot.ValidatedGoStruct, rootSchema *ytypes.Schema) error {
+	if err := ytypes.DeleteNode(rootSchema.RootSchema(), deviceModel, deletes[0]); err != nil {
+		return err
+	}
+	modelAsString, _ := ygot.EmitJSON(deviceModel, &ygot.EmitJSONConfig{
+		Format:         ygot.RFC7951,
+		Indent:         "",
+		SkipValidation: true,
+		RFC7951Config: &ygot.RFC7951JSONConfig{
+			AppendModuleName: true,
+		}})
+
+	rootPath, err := ygot.StringToStructuredPath("/")
+	if err != nil {
+		return err
 	}
+
+	if err := g.Unmarshal([]byte(modelAsString), rootPath, deviceModel); err != nil {
+		return err
+	}
+
 	return nil
 }
 
@@ -301,7 +379,7 @@ func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interfa
 	return resp, nil
 }
 
-// Subscribe calls GNMI subscribe
+// subscribe calls GNMI subscribe.
 func (g *Gnmi) subscribe(ctx context.Context) error {
 	ctx = gnmi.NewContext(ctx, g.config)
 	opts, ok := ctx.Value(types.CtxKeyOpts).(*gnmi.SubscribeOptions)
@@ -330,6 +408,46 @@ func (g *Gnmi) subscribe(ctx context.Context) error {
 	return gnmi.SubscribeErr(ctx, g.client, opts, g.RespChan)
 }
 
+// controlPlaneSubscribe calls gNMI subscribe with a callback for responses and additional device information including
+// an option to stop the subscription.
+func (g *Gnmi) controlPlaneSubscribe(ctx context.Context, subcribeCallbackFunc func(*gpb.SubscribeResponse,
+	*tpInterface.SubscriptionInformation), subscriptionInfo *tpInterface.SubscriptionInformation) error {
+	ctx = gnmi.NewContext(ctx, g.config)
+	opts, ok := ctx.Value(types.CtxKeyOpts).(*gnmi.SubscribeOptions)
+	if !ok {
+		return &errors.ErrInvalidTypeAssertion{
+			Value: ctx.Value(types.CtxKeyOpts),
+			Type:  &gnmi.SubscribeOptions{},
+		}
+	}
+
+	go func() {
+		log.WithFields(log.Fields{
+			"address":  opts.Target,
+			"paths":    opts.Paths,
+			"mode":     opts.Mode,
+			"interval": opts.SampleInterval,
+		}).Info("subscribed to gNMI target")
+		for {
+			resp := <-g.RespChan
+			if resp != nil {
+				// callback to trigger internal event handling process
+				go subcribeCallbackFunc(resp, subscriptionInfo)
+			}
+
+			select {
+			case <-subscriptionInfo.StopContext.Done():
+				if err := subscriptionInfo.StopContext.Err(); err != nil {
+					log.Error(err)
+				}
+				return
+			default:
+			}
+		}
+	}()
+	return gnmi.SubscribeErr(ctx, g.client, opts, g.RespChan)
+}
+
 // Close calls GNMI close
 func (g *Gnmi) Close() error {
 	return nil
diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go
index 46e6aa1be776f51f308b778ca43cdc1302167966..566d6623b37017bf8f63f2c903c6ec715a09279c 100644
--- a/controller/nucleus/principalNetworkDomain.go
+++ b/controller/nucleus/principalNetworkDomain.go
@@ -34,6 +34,7 @@ import (
 
 	"code.fbi.h-da.de/danet/gosdn/controller/store"
 
+	"code.fbi.h-da.de/danet/gosdn/forks/goarista/gnmi"
 	"github.com/google/uuid"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	"github.com/openconfig/ygot/ygot"
@@ -277,15 +278,7 @@ func (pnd *pndImplementation) GetDevice(identifier string) (device.Device, error
 		return nil, err
 	}
 
-	// TODO: We should investigate why we copy the device here.
-	copiedDevice := &CommonDevice{
-		name:  d.Name(),
-		UUID:  d.ID(),
-		Model: d.GetModel(),
-		sbi:   d.SBI(),
-	}
-
-	return copiedDevice, nil
+	return d, nil
 }
 
 // RemoveDevice removes a device from the PND
@@ -562,6 +555,73 @@ func (pnd *pndImplementation) ChangeOND(duid uuid.UUID, operation ppb.ApiOperati
 	return ch.cuid, nil
 }
 
+func (pnd *pndImplementation) SubscribePath(uuid uuid.UUID, subList *ppb.SubscriptionList) error {
+	d, err := pnd.deviceService.Get(store.Query{
+		ID: uuid,
+	})
+	if err != nil {
+		return err
+	}
+
+	mode, err := mapModeToAristaFork(subList.GetMode())
+	if err != nil {
+		return err
+	}
+
+	for _, sub := range subList.Subscription {
+		streamMode, err := mapStreamModeToAristaFork(sub.GetStreamMode())
+		if err != nil {
+			return err
+		}
+
+		opts := &gnmi.SubscribeOptions{
+			Mode:           mode,
+			StreamMode:     streamMode,
+			Paths:          [][]string{splitStringPath(sub.GetPath())},
+			SampleInterval: sub.SampleInterval,
+		}
+
+		ctx := context.Background()
+		ctx = context.WithValue(ctx, types.CtxKeyOpts, opts)
+
+		if err = d.Transport().Subscribe(ctx); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func splitStringPath(s string) []string {
+	return strings.Split(s, "/")
+}
+
+func mapStreamModeToAristaFork(mode ppb.StreamMode) (string, error) {
+	switch mode {
+	case ppb.StreamMode_STREAM_MODE_TARGET_DEFINED:
+		return "target_defined", nil
+	case ppb.StreamMode_STREAM_MODE_ON_CHANGE:
+		return "on_change", nil
+	case ppb.StreamMode_STREAM_MODE_SAMPLE:
+		return "sample", nil
+	default:
+		return "", fmt.Errorf("StreamMode of type: %T is not supported", mode)
+	}
+}
+
+func mapModeToAristaFork(mode ppb.SubscriptionMode) (string, error) {
+	switch mode {
+	case ppb.SubscriptionMode_SUBSCRIPTION_MODE_STREAM:
+		return "stream", nil
+	case ppb.SubscriptionMode_SUBSCRIPTION_MODE_ONCE:
+		return "once", nil
+	case ppb.SubscriptionMode_SUBSCRIPTION_MODE_POLL:
+		return "poll", nil
+	default:
+		return "", fmt.Errorf("SubscriptionMode of type: %T is not supported", mode)
+	}
+}
+
 //nolint
 // handleRollbackError will be implemented in the near future
 func handleRollbackError(id uuid.UUID, err error) {
@@ -864,3 +924,12 @@ func (pnd *pndImplementation) MarshalBSON() ([]byte, error) {
 		Description: pnd.Description,
 	})
 }
+
+// UpdateONDAfterSubscribeResponse takes a device and forwards it to the device service to handle the update.
+func (pnd *pndImplementation) UpdateDeviceAfterSubscribeResponse(device device.Device) error {
+	if err := pnd.deviceService.Update(device); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/controller/nucleus/principalNetworkDomain_test.go b/controller/nucleus/principalNetworkDomain_test.go
index 73043dd766cdda55397112f4ec22039d1efa86de..f62903bd4a5871bf837be80783ed9f148f39c9cc 100644
--- a/controller/nucleus/principalNetworkDomain_test.go
+++ b/controller/nucleus/principalNetworkDomain_test.go
@@ -7,11 +7,13 @@ import (
 	"testing"
 
 	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/csbi"
+	cpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/csbi"
 	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
 	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
 	eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
+	eventInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/event"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
 	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
 	"code.fbi.h-da.de/danet/gosdn/controller/mocks"
@@ -1206,3 +1208,63 @@ func Test_pndImplementation_saveGoStructsToFile(t *testing.T) {
 		})
 	}
 }
+
+func Test_pndImplementation_SubscribePath(t *testing.T) {
+	type fields struct {
+		Name              string
+		Description       string
+		southboundService southbound.Service
+		deviceService     device.Service
+		changes           *store.ChangeStore
+		ID                uuid.UUID
+		csbiClient        cpb.CsbiServiceClient
+		callback          func(uuid.UUID, chan device.Details)
+		eventService      eventInterfaces.Service
+	}
+	type args struct {
+		uuid    uuid.UUID
+		subList *ppb.SubscriptionList
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+	}{
+		//TODO: Implement proper test here!
+		// {
+		//  name: "default",
+		//  args: args{
+		//      uuid: did,
+		//      subList: &ppb.SubscriptionList{
+		//          Subscription: []*ppb.Subscription{
+		//              {
+		//                  Path:           "",
+		//                  StreamMode:     ppb.StreamMode_STREAM_MODE_SAMPLE,
+		//                  SampleInterval: 1000000000, // 1 second
+		//              },
+		//          },
+		//          Mode: ppb.SubscriptionMode_SUBSCRIPTION_MODE_STREAM,
+		//      },
+		//  },
+		// },
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			pnd := &pndImplementation{
+				Name:              tt.fields.Name,
+				Description:       tt.fields.Description,
+				southboundService: tt.fields.southboundService,
+				deviceService:     tt.fields.deviceService,
+				changes:           tt.fields.changes,
+				Id:                tt.fields.ID,
+				csbiClient:        tt.fields.csbiClient,
+				callback:          tt.fields.callback,
+				eventService:      tt.fields.eventService,
+			}
+			if err := pnd.SubscribePath(tt.args.uuid, tt.args.subList); (err != nil) != tt.wantErr {
+				t.Errorf("pndImplementation.SubscribePath() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}