From 3870b1b8bbe696649045342d9d2f13df14469977 Mon Sep 17 00:00:00 2001
From: Malte Bauch <malte.bauch@stud.h-da.de>
Date: Thu, 11 Jan 2024 14:20:28 +0000
Subject: [PATCH] Resolve "AddLink crashes goSDN when Link without correct port
 config is send."

See merge request danet/gosdn!697
---
 .../gnmi/proto/collector/collector.pb.go      |   2 +-
 .../openconfig/gnmi/proto/gnmi/gnmi.pb.go     |   2 +-
 .../gnmi/proto/gnmi_ext/gnmi_ext.pb.go        |   2 +-
 .../openconfig/gnmi/proto/target/target.pb.go |   2 +-
 .../gnmi/testing/fake/proto/fake.pb.go        |   2 +-
 api/go/gosdn/app/app.pb.go                    |   2 +-
 api/go/gosdn/app/app.pb.gw.go                 |  24 +-
 .../configurationmanagement.pb.go             |   2 +-
 .../configurationmanagement.pb.gw.go          |   4 +-
 api/go/gosdn/conflict/conflict.pb.go          |   2 +-
 api/go/gosdn/csbi/csbi.pb.go                  |   2 +-
 .../gosdn/networkelement/networkelement.pb.go |   2 +-
 .../networkelement/networkelement.pb.gw.go    |  62 ++---
 .../plugin-internal/plugin-internal.pb.go     |   2 +-
 .../plugin-registry/plugin-registry.pb.go     |   2 +-
 api/go/gosdn/plugin/plugin.pb.go              |   2 +-
 api/go/gosdn/pnd/pnd.pb.go                    |   2 +-
 api/go/gosdn/pnd/pnd.pb.gw.go                 |  16 +-
 api/go/gosdn/rbac/rbac.pb.go                  |   2 +-
 api/go/gosdn/rbac/rbac.pb.gw.go               |  14 +-
 api/go/gosdn/rbac/role.pb.go                  |   2 +-
 api/go/gosdn/rbac/role.pb.gw.go               |  24 +-
 api/go/gosdn/rbac/user.pb.go                  |   2 +-
 api/go/gosdn/rbac/user.pb.gw.go               |  24 +-
 api/go/gosdn/southbound/southbound.pb.go      |   2 +-
 api/go/gosdn/topology/link.pb.go              |   2 +-
 api/go/gosdn/topology/node.pb.go              |   2 +-
 api/go/gosdn/topology/port.pb.go              |  25 +-
 api/go/gosdn/topology/route.pb.go             |   2 +-
 api/go/gosdn/topology/routingTable.pb.go      |   2 +-
 api/go/gosdn/topology/routingTable.pb.gw.go   |  12 +-
 api/go/gosdn/topology/topology.pb.go          |   2 +-
 api/go/gosdn/topology/topology.pb.gw.go       |  24 +-
 api/go/gosdn/transport/transport.pb.go        |   2 +-
 api/openapiv2/gosdn_northbound.swagger.json   | 215 +++++++++---------
 api/proto/gosdn/topology/port.proto           |   2 +-
 controller/northbound/server/topology.go      |  13 +-
 controller/topology/topologyService.go        |  19 --
 controller/topology/topologyStore.go          |   6 +-
 .../topology_tests/topology_test.go           | 145 ++++++------
 40 files changed, 278 insertions(+), 399 deletions(-)

diff --git a/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go b/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
index 6d1300d3e..c1df7944d 100644
--- a/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/collector/collector.proto
 
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
index 04a5ca73f..7e36c7339 100644
--- a/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/gnmi/gnmi.proto
 
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
index cb846a80a..e35cb6e95 100644
--- a/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto
 
diff --git a/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go b/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
index f2f1437a9..17541f003 100644
--- a/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/target/target.proto
 
diff --git a/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go b/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
index 69d6ce30a..92ca47992 100644
--- a/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
+++ b/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
@@ -4,7 +4,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/testing/fake/proto/fake.proto
 
diff --git a/api/go/gosdn/app/app.pb.go b/api/go/gosdn/app/app.pb.go
index 33c424719..6dbd18794 100644
--- a/api/go/gosdn/app/app.pb.go
+++ b/api/go/gosdn/app/app.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/app/app.proto
 
diff --git a/api/go/gosdn/app/app.pb.gw.go b/api/go/gosdn/app/app.pb.gw.go
index 70a4da26b..c155f8d10 100644
--- a/api/go/gosdn/app/app.pb.gw.go
+++ b/api/go/gosdn/app/app.pb.gw.go
@@ -35,11 +35,7 @@ func request_AppService_Register_0(ctx context.Context, marshaler runtime.Marsha
 	var protoReq AppRegisterRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_AppService_Register_0(ctx context.Context, marshaler runtime.
 	var protoReq AppRegisterRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -69,11 +61,7 @@ func request_AppService_Deregister_0(ctx context.Context, marshaler runtime.Mars
 	var protoReq AppDeregisterRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -86,11 +74,7 @@ func local_request_AppService_Deregister_0(ctx context.Context, marshaler runtim
 	var protoReq AppDeregisterRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
index ece31dc1f..82da12e23 100644
--- a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
+++ b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/configurationmanagement/configurationmanagement.proto
 
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
index 8fe6fc557..865179a93 100644
--- a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
+++ b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
@@ -32,7 +32,7 @@ var _ = utilities.NewDoubleArray
 var _ = metadata.Join
 
 var (
-	filter_ConfigurationManagementService_ExportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_ConfigurationManagementService_ExportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_ConfigurationManagementService_ExportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigurationManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -102,7 +102,7 @@ func local_request_ConfigurationManagementService_ExportSDNConfig_0(ctx context.
 }
 
 var (
-	filter_ConfigurationManagementService_ImportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_ConfigurationManagementService_ImportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_ConfigurationManagementService_ImportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigurationManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
diff --git a/api/go/gosdn/conflict/conflict.pb.go b/api/go/gosdn/conflict/conflict.pb.go
index f58b481bf..98580ed5e 100644
--- a/api/go/gosdn/conflict/conflict.pb.go
+++ b/api/go/gosdn/conflict/conflict.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/conflict/conflict.proto
 
diff --git a/api/go/gosdn/csbi/csbi.pb.go b/api/go/gosdn/csbi/csbi.pb.go
index 61c56a775..7dad543a8 100644
--- a/api/go/gosdn/csbi/csbi.pb.go
+++ b/api/go/gosdn/csbi/csbi.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/csbi/csbi.proto
 
diff --git a/api/go/gosdn/networkelement/networkelement.pb.go b/api/go/gosdn/networkelement/networkelement.pb.go
index 0e1e76ff3..8aa7972ff 100644
--- a/api/go/gosdn/networkelement/networkelement.pb.go
+++ b/api/go/gosdn/networkelement/networkelement.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/networkelement/networkelement.proto
 
diff --git a/api/go/gosdn/networkelement/networkelement.pb.gw.go b/api/go/gosdn/networkelement/networkelement.pb.gw.go
index 4a89623bf..f7fd58adf 100644
--- a/api/go/gosdn/networkelement/networkelement.pb.gw.go
+++ b/api/go/gosdn/networkelement/networkelement.pb.gw.go
@@ -35,11 +35,7 @@ func request_NetworkElementService_Update_0(ctx context.Context, marshaler runti
 	var protoReq UpdateNetworkElementRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_NetworkElementService_Update_0(ctx context.Context, marshaler
 	var protoReq UpdateNetworkElementRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -66,7 +58,7 @@ func local_request_NetworkElementService_Update_0(ctx context.Context, marshaler
 }
 
 var (
-	filter_NetworkElementService_GetAllFlattened_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_NetworkElementService_GetAllFlattened_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_NetworkElementService_GetAllFlattened_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -136,7 +128,7 @@ func local_request_NetworkElementService_GetAllFlattened_0(ctx context.Context,
 }
 
 var (
-	filter_NetworkElementService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1}, Base: []int{1, 2, 4, 0, 0, 0, 0}, Check: []int{0, 1, 1, 2, 2, 3, 3}}
+	filter_NetworkElementService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
 )
 
 func request_NetworkElementService_Get_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -229,11 +221,7 @@ func request_NetworkElementService_AddList_0(ctx context.Context, marshaler runt
 	var protoReq AddListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -263,11 +251,7 @@ func local_request_NetworkElementService_AddList_0(ctx context.Context, marshale
 	var protoReq AddListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -294,7 +278,7 @@ func local_request_NetworkElementService_AddList_0(ctx context.Context, marshale
 }
 
 var (
-	filter_NetworkElementService_GetPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1, "path": 2}, Base: []int{1, 2, 4, 6, 0, 0, 0, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 2, 3, 3, 4, 4}}
+	filter_NetworkElementService_GetPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1, "path": 2}, Base: []int{1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4}}
 )
 
 func request_NetworkElementService_GetPath_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -404,7 +388,7 @@ func local_request_NetworkElementService_GetPath_0(ctx context.Context, marshale
 }
 
 var (
-	filter_NetworkElementService_GetIntendedPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1, "intended_path": 2, "intendedPath": 3}, Base: []int{1, 2, 4, 5, 6, 0, 0, 0, 0, 0, 0}, Check: []int{0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5}}
+	filter_NetworkElementService_GetIntendedPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1, "intended_path": 2}, Base: []int{1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 1, 1, 2, 3, 4}}
 )
 
 func request_NetworkElementService_GetIntendedPath_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -517,11 +501,7 @@ func request_NetworkElementService_SetPathList_0(ctx context.Context, marshaler
 	var protoReq SetPathListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -551,11 +531,7 @@ func local_request_NetworkElementService_SetPathList_0(ctx context.Context, mars
 	var protoReq SetPathListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -582,7 +558,7 @@ func local_request_NetworkElementService_SetPathList_0(ctx context.Context, mars
 }
 
 var (
-	filter_NetworkElementService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1}, Base: []int{1, 2, 4, 0, 0, 0, 0}, Check: []int{0, 1, 1, 2, 2, 3, 3}}
+	filter_NetworkElementService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "mneid": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
 )
 
 func request_NetworkElementService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -672,7 +648,7 @@ func local_request_NetworkElementService_Delete_0(ctx context.Context, marshaler
 }
 
 var (
-	filter_NetworkElementService_GetChangeList_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_NetworkElementService_GetChangeList_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_NetworkElementService_GetChangeList_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -742,7 +718,7 @@ func local_request_NetworkElementService_GetChangeList_0(ctx context.Context, ma
 }
 
 var (
-	filter_NetworkElementService_GetChange_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "cuid": 1}, Base: []int{1, 2, 4, 0, 0, 0, 0}, Check: []int{0, 1, 1, 2, 2, 3, 3}}
+	filter_NetworkElementService_GetChange_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0, "cuid": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
 )
 
 func request_NetworkElementService_GetChange_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -835,11 +811,7 @@ func request_NetworkElementService_SetChangeList_0(ctx context.Context, marshale
 	var protoReq SetChangeListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -869,11 +841,7 @@ func local_request_NetworkElementService_SetChangeList_0(ctx context.Context, ma
 	var protoReq SetChangeListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
diff --git a/api/go/gosdn/plugin-internal/plugin-internal.pb.go b/api/go/gosdn/plugin-internal/plugin-internal.pb.go
index 436d0a8a3..2121ed858 100644
--- a/api/go/gosdn/plugin-internal/plugin-internal.pb.go
+++ b/api/go/gosdn/plugin-internal/plugin-internal.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/plugin-internal/plugin-internal.proto
 
diff --git a/api/go/gosdn/plugin-registry/plugin-registry.pb.go b/api/go/gosdn/plugin-registry/plugin-registry.pb.go
index b8cff49be..74f0bb375 100644
--- a/api/go/gosdn/plugin-registry/plugin-registry.pb.go
+++ b/api/go/gosdn/plugin-registry/plugin-registry.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/plugin-registry/plugin-registry.proto
 
diff --git a/api/go/gosdn/plugin/plugin.pb.go b/api/go/gosdn/plugin/plugin.pb.go
index 5d20c3b47..ba4ee0b2b 100644
--- a/api/go/gosdn/plugin/plugin.pb.go
+++ b/api/go/gosdn/plugin/plugin.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/plugin/plugin.proto
 
diff --git a/api/go/gosdn/pnd/pnd.pb.go b/api/go/gosdn/pnd/pnd.pb.go
index 7ac915d60..4a623c69e 100644
--- a/api/go/gosdn/pnd/pnd.pb.go
+++ b/api/go/gosdn/pnd/pnd.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/pnd/pnd.proto
 
diff --git a/api/go/gosdn/pnd/pnd.pb.gw.go b/api/go/gosdn/pnd/pnd.pb.gw.go
index aeb7fc147..ffd300943 100644
--- a/api/go/gosdn/pnd/pnd.pb.gw.go
+++ b/api/go/gosdn/pnd/pnd.pb.gw.go
@@ -32,7 +32,7 @@ var _ = utilities.NewDoubleArray
 var _ = metadata.Join
 
 var (
-	filter_PndService_GetPnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_PndService_GetPnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_PndService_GetPnd_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -141,11 +141,7 @@ func request_PndService_CreatePndList_0(ctx context.Context, marshaler runtime.M
 	var protoReq CreatePndListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -158,11 +154,7 @@ func local_request_PndService_CreatePndList_0(ctx context.Context, marshaler run
 	var protoReq CreatePndListRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -172,7 +164,7 @@ func local_request_PndService_CreatePndList_0(ctx context.Context, marshaler run
 }
 
 var (
-	filter_PndService_DeletePnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_PndService_DeletePnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_PndService_DeletePnd_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
diff --git a/api/go/gosdn/rbac/rbac.pb.go b/api/go/gosdn/rbac/rbac.pb.go
index 9da82513a..e91dcd95d 100644
--- a/api/go/gosdn/rbac/rbac.pb.go
+++ b/api/go/gosdn/rbac/rbac.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/rbac/rbac.proto
 
diff --git a/api/go/gosdn/rbac/rbac.pb.gw.go b/api/go/gosdn/rbac/rbac.pb.gw.go
index 5fb25158f..4ccb7da95 100644
--- a/api/go/gosdn/rbac/rbac.pb.gw.go
+++ b/api/go/gosdn/rbac/rbac.pb.gw.go
@@ -35,11 +35,7 @@ func request_AuthService_Login_0(ctx context.Context, marshaler runtime.Marshale
 	var protoReq LoginRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_AuthService_Login_0(ctx context.Context, marshaler runtime.Ma
 	var protoReq LoginRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -66,7 +58,7 @@ func local_request_AuthService_Login_0(ctx context.Context, marshaler runtime.Ma
 }
 
 var (
-	filter_AuthService_Logout_0 = &utilities.DoubleArray{Encoding: map[string]int{"username": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}}
+	filter_AuthService_Logout_0 = &utilities.DoubleArray{Encoding: map[string]int{"username": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 )
 
 func request_AuthService_Logout_0(ctx context.Context, marshaler runtime.Marshaler, client AuthServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
diff --git a/api/go/gosdn/rbac/role.pb.go b/api/go/gosdn/rbac/role.pb.go
index 3f2c7759f..e2f89ca19 100644
--- a/api/go/gosdn/rbac/role.pb.go
+++ b/api/go/gosdn/rbac/role.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/rbac/role.proto
 
diff --git a/api/go/gosdn/rbac/role.pb.gw.go b/api/go/gosdn/rbac/role.pb.gw.go
index 77d5ab670..827c06904 100644
--- a/api/go/gosdn/rbac/role.pb.gw.go
+++ b/api/go/gosdn/rbac/role.pb.gw.go
@@ -35,11 +35,7 @@ func request_RoleService_CreateRoles_0(ctx context.Context, marshaler runtime.Ma
 	var protoReq CreateRolesRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_RoleService_CreateRoles_0(ctx context.Context, marshaler runt
 	var protoReq CreateRolesRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -141,11 +133,7 @@ func request_RoleService_UpdateRoles_0(ctx context.Context, marshaler runtime.Ma
 	var protoReq UpdateRolesRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -158,11 +146,7 @@ func local_request_RoleService_UpdateRoles_0(ctx context.Context, marshaler runt
 	var protoReq UpdateRolesRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
diff --git a/api/go/gosdn/rbac/user.pb.go b/api/go/gosdn/rbac/user.pb.go
index 929aad7da..9a72c8216 100644
--- a/api/go/gosdn/rbac/user.pb.go
+++ b/api/go/gosdn/rbac/user.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/rbac/user.proto
 
diff --git a/api/go/gosdn/rbac/user.pb.gw.go b/api/go/gosdn/rbac/user.pb.gw.go
index 944d18017..4d484df0c 100644
--- a/api/go/gosdn/rbac/user.pb.gw.go
+++ b/api/go/gosdn/rbac/user.pb.gw.go
@@ -35,11 +35,7 @@ func request_UserService_CreateUsers_0(ctx context.Context, marshaler runtime.Ma
 	var protoReq CreateUsersRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_UserService_CreateUsers_0(ctx context.Context, marshaler runt
 	var protoReq CreateUsersRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -141,11 +133,7 @@ func request_UserService_UpdateUsers_0(ctx context.Context, marshaler runtime.Ma
 	var protoReq UpdateUsersRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -158,11 +146,7 @@ func local_request_UserService_UpdateUsers_0(ctx context.Context, marshaler runt
 	var protoReq UpdateUsersRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
diff --git a/api/go/gosdn/southbound/southbound.pb.go b/api/go/gosdn/southbound/southbound.pb.go
index a2a930854..2f301e457 100644
--- a/api/go/gosdn/southbound/southbound.pb.go
+++ b/api/go/gosdn/southbound/southbound.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/southbound/southbound.proto
 
diff --git a/api/go/gosdn/topology/link.pb.go b/api/go/gosdn/topology/link.pb.go
index 8863beab7..b6773cc53 100644
--- a/api/go/gosdn/topology/link.pb.go
+++ b/api/go/gosdn/topology/link.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/topology/link.proto
 
diff --git a/api/go/gosdn/topology/node.pb.go b/api/go/gosdn/topology/node.pb.go
index f2d07bbfb..68734d228 100644
--- a/api/go/gosdn/topology/node.pb.go
+++ b/api/go/gosdn/topology/node.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/topology/node.proto
 
diff --git a/api/go/gosdn/topology/port.pb.go b/api/go/gosdn/topology/port.pb.go
index 72b407f41..a3bff28fa 100644
--- a/api/go/gosdn/topology/port.pb.go
+++ b/api/go/gosdn/topology/port.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/topology/port.proto
 
@@ -172,22 +172,23 @@ var file_gosdn_topology_port_proto_rawDesc = []byte{
 	0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69,
 	0x70, 0x12, 0x2a, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74,
 	0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52,
-	0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0xae, 0x01,
+	0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0xb6, 0x01,
 	0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
 	0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
+	0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
 	0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
-	0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61,
-	0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61,
-	0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x34,
-	0x5a, 0x32, 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, 0x74, 0x6f, 0x70, 0x6f,
-	0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01,
+	0x01, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x12, 0x34, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6c,
+	0x69, 0x63, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65,
+	0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x34, 0x5a, 0x32, 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, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/api/go/gosdn/topology/route.pb.go b/api/go/gosdn/topology/route.pb.go
index 258777323..565f6d962 100644
--- a/api/go/gosdn/topology/route.pb.go
+++ b/api/go/gosdn/topology/route.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/topology/route.proto
 
diff --git a/api/go/gosdn/topology/routingTable.pb.go b/api/go/gosdn/topology/routingTable.pb.go
index 50f107881..841185ecb 100644
--- a/api/go/gosdn/topology/routingTable.pb.go
+++ b/api/go/gosdn/topology/routingTable.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/topology/routingTable.proto
 
diff --git a/api/go/gosdn/topology/routingTable.pb.gw.go b/api/go/gosdn/topology/routingTable.pb.gw.go
index afaa6de87..c996d57a5 100644
--- a/api/go/gosdn/topology/routingTable.pb.gw.go
+++ b/api/go/gosdn/topology/routingTable.pb.gw.go
@@ -35,11 +35,7 @@ func request_RoutingTableService_AddRoutingTable_0(ctx context.Context, marshale
 	var protoReq AddRoutingTableRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_RoutingTableService_AddRoutingTable_0(ctx context.Context, ma
 	var protoReq AddRoutingTableRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
diff --git a/api/go/gosdn/topology/topology.pb.go b/api/go/gosdn/topology/topology.pb.go
index 875d41d59..5450328c2 100644
--- a/api/go/gosdn/topology/topology.pb.go
+++ b/api/go/gosdn/topology/topology.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/topology/topology.proto
 
diff --git a/api/go/gosdn/topology/topology.pb.gw.go b/api/go/gosdn/topology/topology.pb.gw.go
index bd096b794..d15549de5 100644
--- a/api/go/gosdn/topology/topology.pb.gw.go
+++ b/api/go/gosdn/topology/topology.pb.gw.go
@@ -35,11 +35,7 @@ func request_TopologyService_AddLink_0(ctx context.Context, marshaler runtime.Ma
 	var protoReq AddLinkRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -52,11 +48,7 @@ func local_request_TopologyService_AddLink_0(ctx context.Context, marshaler runt
 	var protoReq AddLinkRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -105,11 +97,7 @@ func request_TopologyService_UpdateLink_0(ctx context.Context, marshaler runtime
 	var protoReq UpdateLinkRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
@@ -122,11 +110,7 @@ func local_request_TopologyService_UpdateLink_0(ctx context.Context, marshaler r
 	var protoReq UpdateLinkRequest
 	var metadata runtime.ServerMetadata
 
-	newReader, berr := utilities.IOReaderFactory(req.Body)
-	if berr != nil {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
-	}
-	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 
diff --git a/api/go/gosdn/transport/transport.pb.go b/api/go/gosdn/transport/transport.pb.go
index 84e199328..2d8de2ee9 100644
--- a/api/go/gosdn/transport/transport.pb.go
+++ b/api/go/gosdn/transport/transport.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.31.0
+// 	protoc-gen-go v1.32.0
 // 	protoc        (unknown)
 // source: gosdn/transport/transport.proto
 
diff --git a/api/openapiv2/gosdn_northbound.swagger.json b/api/openapiv2/gosdn_northbound.swagger.json
index e91ebf37b..6658ae466 100644
--- a/api/openapiv2/gosdn_northbound.swagger.json
+++ b/api/openapiv2/gosdn_northbound.swagger.json
@@ -87,7 +87,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -120,7 +120,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -159,7 +159,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -204,7 +204,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -237,7 +237,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -275,7 +275,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -308,7 +308,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -347,7 +347,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -378,7 +378,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -411,7 +411,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -450,7 +450,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -487,7 +487,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -503,21 +503,7 @@
             "in": "body",
             "required": true,
             "schema": {
-              "type": "object",
-              "properties": {
-                "timestamp": {
-                  "type": "string",
-                  "format": "int64",
-                  "description": "Timestamp in nanoseconds since Epoch."
-                },
-                "change": {
-                  "type": "array",
-                  "items": {
-                    "type": "object",
-                    "$ref": "#/definitions/networkelementSetChange"
-                  }
-                }
-              }
+              "$ref": "#/definitions/NetworkElementServiceSetChangeListBody"
             }
           }
         ],
@@ -540,7 +526,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -590,7 +576,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -635,7 +621,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -672,7 +658,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -688,21 +674,7 @@
             "in": "body",
             "required": true,
             "schema": {
-              "type": "object",
-              "properties": {
-                "timestamp": {
-                  "type": "string",
-                  "format": "int64",
-                  "description": "Timestamp in nanoseconds since Epoch."
-                },
-                "mne": {
-                  "type": "array",
-                  "items": {
-                    "type": "object",
-                    "$ref": "#/definitions/networkelementSetMne"
-                  }
-                }
-              }
+              "$ref": "#/definitions/NetworkElementServiceAddListBody"
             }
           }
         ],
@@ -725,7 +697,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -741,21 +713,7 @@
             "in": "body",
             "required": true,
             "schema": {
-              "type": "object",
-              "properties": {
-                "timestamp": {
-                  "type": "string",
-                  "format": "int64",
-                  "description": "Timestamp in nanoseconds since Epoch."
-                },
-                "changeRequest": {
-                  "type": "array",
-                  "items": {
-                    "type": "object",
-                    "$ref": "#/definitions/networkelementChangeRequest"
-                  }
-                }
-              }
+              "$ref": "#/definitions/NetworkElementServiceSetPathListBody"
             }
           }
         ],
@@ -778,7 +736,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -823,7 +781,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -873,7 +831,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -924,7 +882,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -957,7 +915,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -989,7 +947,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1022,7 +980,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1064,7 +1022,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1112,7 +1070,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1156,7 +1114,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1188,7 +1146,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1219,7 +1177,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1251,7 +1209,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1288,7 +1246,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1319,7 +1277,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1351,7 +1309,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1388,7 +1346,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1421,7 +1379,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1453,7 +1411,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1486,7 +1444,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1528,7 +1486,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1573,7 +1531,7 @@
           "default": {
             "description": "An unexpected error response.",
             "schema": {
-              "$ref": "#/definitions/rpcStatus"
+              "$ref": "#/definitions/googlerpcStatus"
             }
           }
         },
@@ -1615,6 +1573,57 @@
       "default": "ALL",
       "description": "Type of elements within the data tree.\n\n - ALL: All data elements.\n - CONFIG: Config (rw) only elements.\n - STATE: State (ro) only elements.\n - OPERATIONAL: Data elements marked in the schema as operational. This refers to data\nelements whose value relates to the state of processes or interactions\nrunning on the device."
     },
+    "NetworkElementServiceAddListBody": {
+      "type": "object",
+      "properties": {
+        "timestamp": {
+          "type": "string",
+          "format": "int64",
+          "description": "Timestamp in nanoseconds since Epoch."
+        },
+        "mne": {
+          "type": "array",
+          "items": {
+            "type": "object",
+            "$ref": "#/definitions/networkelementSetMne"
+          }
+        }
+      }
+    },
+    "NetworkElementServiceSetChangeListBody": {
+      "type": "object",
+      "properties": {
+        "timestamp": {
+          "type": "string",
+          "format": "int64",
+          "description": "Timestamp in nanoseconds since Epoch."
+        },
+        "change": {
+          "type": "array",
+          "items": {
+            "type": "object",
+            "$ref": "#/definitions/networkelementSetChange"
+          }
+        }
+      }
+    },
+    "NetworkElementServiceSetPathListBody": {
+      "type": "object",
+      "properties": {
+        "timestamp": {
+          "type": "string",
+          "format": "int64",
+          "description": "Timestamp in nanoseconds since Epoch."
+        },
+        "changeRequest": {
+          "type": "array",
+          "items": {
+            "type": "object",
+            "$ref": "#/definitions/networkelementChangeRequest"
+          }
+        }
+      }
+    },
     "SubscriptionListMode": {
       "type": "string",
       "enum": [
@@ -2834,6 +2843,25 @@
       },
       "description": "Value is the main message that will trigger a stream of updates for a given\npath.  A file containing a list of values can be used to simulate a network\ndevice for integration tests."
     },
+    "googlerpcStatus": {
+      "type": "object",
+      "properties": {
+        "code": {
+          "type": "integer",
+          "format": "int32"
+        },
+        "message": {
+          "type": "string"
+        },
+        "details": {
+          "type": "array",
+          "items": {
+            "type": "object",
+            "$ref": "#/definitions/protobufAny"
+          }
+        }
+      }
+    },
     "gosdncsbiDeleteResponse": {
       "type": "object",
       "properties": {
@@ -3968,25 +3996,6 @@
         }
       }
     },
-    "rpcStatus": {
-      "type": "object",
-      "properties": {
-        "code": {
-          "type": "integer",
-          "format": "int32"
-        },
-        "message": {
-          "type": "string"
-        },
-        "details": {
-          "type": "array",
-          "items": {
-            "type": "object",
-            "$ref": "#/definitions/protobufAny"
-          }
-        }
-      }
-    },
     "topologyAddLinkRequest": {
       "type": "object",
       "properties": {
diff --git a/api/proto/gosdn/topology/port.proto b/api/proto/gosdn/topology/port.proto
index ceaf83d93..6a10a7b84 100644
--- a/api/proto/gosdn/topology/port.proto
+++ b/api/proto/gosdn/topology/port.proto
@@ -19,6 +19,6 @@ message Configuration {
 message Port {
     string id = 1;
     string name = 2 [(buf.validate.field).string.min_len = 1 ];
-    Configuration configuration = 3;
+    Configuration configuration = 3 [(buf.validate.field).required = true];
     conflict.Metadata metadata = 4;
 }
diff --git a/controller/northbound/server/topology.go b/controller/northbound/server/topology.go
index 099afe534..27e7dd361 100644
--- a/controller/northbound/server/topology.go
+++ b/controller/northbound/server/topology.go
@@ -78,8 +78,19 @@ func (t *TopologyServer) AddLink(ctx context.Context, request *topopb.AddLinkReq
 		return nil, status.Errorf(codes.Aborted, "%v", err)
 	}
 
+	// check if UUID is set
+	var id uuid.UUID
+	if requestId := request.Link.Id; requestId != "" {
+		id, err = uuid.Parse(requestId)
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		id = uuid.New()
+	}
+
 	link := links.Link{
-		ID:         uuid.New(),
+		ID:         id,
 		Name:       request.Link.Name,
 		SourceNode: sourceNode,
 		SourcePort: sourcePort,
diff --git a/controller/topology/topologyService.go b/controller/topology/topologyService.go
index b562a9d7b..a1edd6464 100644
--- a/controller/topology/topologyService.go
+++ b/controller/topology/topologyService.go
@@ -51,25 +51,6 @@ func NewTopologyService(
 
 // AddLink adds a new link to the topology.
 func (t *TopoService) AddLink(link links.Link) error {
-	// These checks are also happening in the current NBI implementation.
-	// This should be refactored to only to these checks here.
-	// _, err := t.nodeService.EnsureExists(link.SourceNode)
-	// if err != nil {
-	// 	return err
-	// }
-	// _, err = t.portService.EnsureExists(link.SourcePort)
-	// if err != nil {
-	// 	return err
-	// }
-
-	// _, err = t.nodeService.EnsureExists(link.TargetNode)
-	// if err != nil {
-	// 	return err
-	// }
-	// _, err = t.portService.EnsureExists(link.TargetPort)
-	// if err != nil {
-	// 	return err
-	// }
 	ctx := context.Background()
 
 	err := t.store.Add(ctx, link)
diff --git a/controller/topology/topologyStore.go b/controller/topology/topologyStore.go
index 009d1eab7..f434248f2 100644
--- a/controller/topology/topologyStore.go
+++ b/controller/topology/topologyStore.go
@@ -62,7 +62,7 @@ func (s *DatabaseTopologyStore) Get(ctx context.Context, query query.Query) (lin
 }
 
 func (s *DatabaseTopologyStore) getByID(ctx context.Context, idOfTopology uuid.UUID) (loadedTopology links.Link, err error) {
-	result := s.collection.FindOne(ctx, bson.D{primitive.E{Key: "_id", Value: idOfTopology.String()}})
+	result := s.collection.FindOne(ctx, bson.D{primitive.E{Key: "_id", Value: idOfTopology}})
 	if result == nil {
 		return loadedTopology, customerrs.CouldNotFindError{ID: idOfTopology}
 	}
@@ -136,7 +136,7 @@ func (s *DatabaseTopologyStore) Update(ctx context.Context, linkToUpdate links.L
 
 	err = s.collection.
 		FindOneAndUpdate(
-			ctx, bson.M{"_id": linkToUpdate.ID.String()}, update, &opt).
+			ctx, bson.M{"_id": linkToUpdate.ID}, update, &opt).
 		Decode(&updatedLink)
 	if err != nil {
 		return customerrs.CouldNotUpdateError{Identifier: linkToUpdate.ID, Type: linkToUpdate, Err: err}
@@ -147,7 +147,7 @@ func (s *DatabaseTopologyStore) Update(ctx context.Context, linkToUpdate links.L
 
 // Delete deletes a link from the link store.
 func (s *DatabaseTopologyStore) Delete(ctx context.Context, linkToDelete links.Link) (err error) {
-	_, err = s.collection.DeleteOne(ctx, bson.D{primitive.E{Key: linkToDelete.ID.String()}})
+	_, err = s.collection.DeleteOne(ctx, bson.D{primitive.E{Key: "_id", Value: linkToDelete.ID}})
 	if err != nil {
 		return err
 	}
diff --git a/integration-tests/topology_tests/topology_test.go b/integration-tests/topology_tests/topology_test.go
index 5e6a44baf..54c625541 100644
--- a/integration-tests/topology_tests/topology_test.go
+++ b/integration-tests/topology_tests/topology_test.go
@@ -78,81 +78,78 @@ func TestCreateTopologyAndGetIt(t *testing.T) {
 	assert.Equal(t, int64(24), getTopolgyResponse.Toplogy.Links[0].TargetPort.Configuration.PrefixLength)
 }
 
-// goSDN crashed due to validation errors in the topology service. If bug is fixed, uncomment and finish this test.
-//func TestCreateTopologyFailsValidation(t *testing.T) {
-//	defer integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig)
-//
-//	addLinkRequest := topologyPb.AddLinkRequest{
-//		Link: &topologyPb.Link{
-//			Name:       "Link1",
-//			SourceNode: &topologyPb.Node{Name: "Node1"},
-//			TargetNode: &topologyPb.Node{Name: "Node2"},
-//			SourcePort: &topologyPb.Port{Name: "Port1"},
-//			TargetPort: &topologyPb.Port{Name: "Port2"}},
-//	}
-//
-//	topologyService := topologyPb.NewTopologyServiceClient(conn)
-//	_, err := topologyService.AddLink(ctx, &addLinkRequest)
-//
-//	if err == nil {
-//		t.Errorf("Test expected an error, none received.")
-//	}
-//}
+func TestCreateTopologyFailsValidation(t *testing.T) {
+	defer integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig)
+
+	addLinkRequest := topologyPb.AddLinkRequest{
+		Link: &topologyPb.Link{
+			Name:       "Link1",
+			SourceNode: &topologyPb.Node{Name: "Node1"},
+			TargetNode: &topologyPb.Node{Name: "Node2"},
+			SourcePort: &topologyPb.Port{Name: "Port1"},
+			TargetPort: &topologyPb.Port{Name: "Port2"}},
+	}
+
+	topologyService := topologyPb.NewTopologyServiceClient(conn)
+	resp, err := topologyService.AddLink(ctx, &addLinkRequest)
+	assert.Error(t, err, "Test expected an error, none received.")
+	assert.Nil(t, resp, "Test expects the resp to be nil if an error is thrown beforehand.")
+}
 
 // Test that creates a topology and then deletes it and checks that all topologies are deleted.
 
 // Can't delete topology because of bug in goSDN. If bug is fixed, uncomment and finish this test.
-//func TestCreateThenDeleteTopologyAndGetEmptyTopologies(t *testing.T) {
-//	defer integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig)
-//
-//	addLinkRequest := topologyPb.AddLinkRequest{
-//		Link: &topologyPb.Link{
-//			Name:       "Link1",
-//			SourceNode: &topologyPb.Node{Name: "Node1"},
-//			TargetNode: &topologyPb.Node{Name: "Node2"},
-//			SourcePort: &topologyPb.Port{Name: "Port1",
-//				Configuration: &topologyPb.Configuration{
-//					Ip:           "10.0.0.1",
-//					PrefixLength: 24}},
-//			TargetPort: &topologyPb.Port{Name: "Port2",
-//				Configuration: &topologyPb.Configuration{
-//					Ip:           "10.0.0.2",
-//					PrefixLength: 24}}},
-//	}
-//
-//	topologyService := topologyPb.NewTopologyServiceClient(conn)
-//	_, err := topologyService.AddLink(ctx, &addLinkRequest)
-//	if err != nil {
-//		t.Errorf("Error while adding link: %v", err)
-//	}
-//
-//	getTopolgyResponse, err := topologyService.GetTopology(ctx, &topologyPb.GetTopologyRequest{})
-//	if err != nil {
-//		t.Errorf("Error while getting topology: %v", err)
-//	}
-//
-//	assert.Equal(t, 1, len(getTopolgyResponse.Toplogy.Links))
-//	assert.Equal(t, "Link1", getTopolgyResponse.Toplogy.Links[0].Name)
-//	assert.Equal(t, "Node1", getTopolgyResponse.Toplogy.Links[0].SourceNode.Name)
-//	assert.Equal(t, "Node2", getTopolgyResponse.Toplogy.Links[0].TargetNode.Name)
-//	assert.Equal(t, "Port1", getTopolgyResponse.Toplogy.Links[0].SourcePort.Name)
-//	assert.Equal(t, "10.0.0.1", getTopolgyResponse.Toplogy.Links[0].SourcePort.Configuration.Ip)
-//	assert.Equal(t, int64(24), getTopolgyResponse.Toplogy.Links[0].SourcePort.Configuration.PrefixLength)
-//	assert.Equal(t, "Port2", getTopolgyResponse.Toplogy.Links[0].TargetPort.Name)
-//	assert.Equal(t, "10.0.0.2", getTopolgyResponse.Toplogy.Links[0].TargetPort.Configuration.Ip)
-//	assert.Equal(t, int64(24), getTopolgyResponse.Toplogy.Links[0].TargetPort.Configuration.PrefixLength)
-//
-//	deleteLinkRequest := topologyPb.DeleteLinkRequest{Id: getTopolgyResponse.Toplogy.Links[0].Id}
-//	_, err = topologyService.DeleteLink(ctx, &deleteLinkRequest)
-//	if err != nil {
-//		t.Errorf("Error while deleting link: %v", err)
-//	}
-//	getTopologyRequest := &topologyPb.GetTopologyRequest{}
-//	getTopologyResponse, err := topologyService.GetTopology(ctx, getTopologyRequest)
-//	if err != nil {
-//		t.Errorf("Error while getting topologies: %v", err)
-//	}
-//
-//	assert.Equal(t, 0, len(getTopologyResponse.Toplogy.Links))
-//}
-//
+func TestCreateThenDeleteTopologyAndGetEmptyTopologies(t *testing.T) {
+	defer integration_test_utils.ApplySDNConfig(conn, ctx, defaultSDNConfig)
+
+	addLinkRequest := topologyPb.AddLinkRequest{
+		Link: &topologyPb.Link{
+			Id:         "8a01b8b0-6244-42bf-b72a-3821efc1a353",
+			Name:       "Link1",
+			SourceNode: &topologyPb.Node{Name: "Node1"},
+			TargetNode: &topologyPb.Node{Name: "Node2"},
+			SourcePort: &topologyPb.Port{Name: "Port1",
+				Configuration: &topologyPb.Configuration{
+					Ip:           "10.0.0.1",
+					PrefixLength: 24}},
+			TargetPort: &topologyPb.Port{Name: "Port2",
+				Configuration: &topologyPb.Configuration{
+					Ip:           "10.0.0.2",
+					PrefixLength: 24}}},
+	}
+
+	topologyService := topologyPb.NewTopologyServiceClient(conn)
+	_, err := topologyService.AddLink(ctx, &addLinkRequest)
+	if err != nil {
+		t.Errorf("Error while adding link: %v", err)
+	}
+
+	getTopolgyResponse, err := topologyService.GetTopology(ctx, &topologyPb.GetTopologyRequest{})
+	if err != nil {
+		t.Errorf("Error while getting topology: %v", err)
+	}
+
+	assert.Equal(t, 1, len(getTopolgyResponse.Toplogy.Links))
+	assert.Equal(t, "Link1", getTopolgyResponse.Toplogy.Links[0].Name)
+	assert.Equal(t, "Node1", getTopolgyResponse.Toplogy.Links[0].SourceNode.Name)
+	assert.Equal(t, "Node2", getTopolgyResponse.Toplogy.Links[0].TargetNode.Name)
+	assert.Equal(t, "Port1", getTopolgyResponse.Toplogy.Links[0].SourcePort.Name)
+	assert.Equal(t, "10.0.0.1", getTopolgyResponse.Toplogy.Links[0].SourcePort.Configuration.Ip)
+	assert.Equal(t, int64(24), getTopolgyResponse.Toplogy.Links[0].SourcePort.Configuration.PrefixLength)
+	assert.Equal(t, "Port2", getTopolgyResponse.Toplogy.Links[0].TargetPort.Name)
+	assert.Equal(t, "10.0.0.2", getTopolgyResponse.Toplogy.Links[0].TargetPort.Configuration.Ip)
+	assert.Equal(t, int64(24), getTopolgyResponse.Toplogy.Links[0].TargetPort.Configuration.PrefixLength)
+
+	deleteLinkRequest := topologyPb.DeleteLinkRequest{Id: getTopolgyResponse.Toplogy.Links[0].Id}
+	_, err = topologyService.DeleteLink(ctx, &deleteLinkRequest)
+	if err != nil {
+		t.Errorf("Error while deleting link: %v", err)
+	}
+	getTopologyRequest := &topologyPb.GetTopologyRequest{}
+	getTopologyResponse, err := topologyService.GetTopology(ctx, getTopologyRequest)
+	if err != nil {
+		t.Errorf("Error while getting topologies: %v", err)
+	}
+
+	assert.Equal(t, 0, len(getTopologyResponse.Toplogy.Links))
+}
-- 
GitLab