diff --git a/applications/rtdt-manager/.gitignore b/applications/rtdt-manager/.gitignore
index 62a0f8364060161d22ddcd805a50d2e653d5b507..97e240260a403059f75e4876461ea51d001f1ab0 100644
--- a/applications/rtdt-manager/.gitignore
+++ b/applications/rtdt-manager/.gitignore
@@ -1,2 +1,3 @@
 *.bak
+*.BAK
 twin*
diff --git a/applications/rtdt-manager/data/venv_sdnconfig_full.json b/applications/rtdt-manager/data/venv_sdnconfig_full.json
index 282dbdfee5e7d058ce5fda78238588ebd59fd69c..32fc735a2a851bd5bfab6f86eb11bbd93610d3a5 100644
--- a/applications/rtdt-manager/data/venv_sdnconfig_full.json
+++ b/applications/rtdt-manager/data/venv_sdnconfig_full.json
@@ -212,7 +212,7 @@
       }
     }
   ],
-  "plugins": null,
+  "plugins": [],
   "networkelements": [
     {
       "id": "db563e8d-0755-4df7-8458-56e3242b1cd4",
diff --git a/applications/rtdt-manager/main.go b/applications/rtdt-manager/main.go
index e595f0b65644f7bb24d6cc6913f13062b96c6498..df792348b185281792cadc0beb2cec04b6bcf88c 100644
--- a/applications/rtdt-manager/main.go
+++ b/applications/rtdt-manager/main.go
@@ -56,15 +56,25 @@ func main() {
 		fmt.Println("Couldn't initialize rtdt-manager, quitting!")
 		return
 	}
-	// Deploy the realnet as VEnv (containerlab)
+	// Load the sdnconfig .json file that contain network elements and topology information
+	// of the physical network first as a starting point. In a deployed physical network, this information
+	// would also be retrievable, making this as realistic as it can be.
 	sdnConfig := sdnconfig.NewSdnConfig()
-	sdnConfig.LoadSdnConfig(sdnConfigPath)
+	err = sdnConfig.LoadSdnConfig(sdnConfigPath)
+	if err != nil {
+		fmt.Printf("In main(): %v\n", err)
+		return
+	}
+	// This loads the base containerlab config file that contains information on how to start
+	// gosdn, rabbitmq, pluginregistry and mongodb+mongodbexpress as containers
 	clabBaseConfig, err := clabconfig.LoadConfig(clabConfigName)
 	if err != nil {
 		fmt.Printf("In main(): %v\n", err)
 		return
 	}
-	// Start virtual environment for realnet
+
+	// Start virtual environment for physical network. This can be skipped in an environment
+	// where an actual physical network is already running.
 	err = rtdtMan.LaunchRealnetVEnv("realnet", sdnConfig, clabBaseConfig)
 	if err != nil {
 		fmt.Printf("In main(): %v\n", err)
@@ -73,7 +83,7 @@ func main() {
 
 	err = rtdtMan.InitEventSystem()
 	if err != nil {
-        fmt.Printf("In main(): %v\n", err)
+		fmt.Printf("In main(): %v\n", err)
 		return
 	}
 	// Do performance tests of realnet before starting twin
diff --git a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go
index 7413e0bd7e41d5b974aa8e197ff2f57d13df8c73..6404a9e3a12d9f669ff521a033bb9c3621a2279b 100644
--- a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go
+++ b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go
@@ -43,17 +43,18 @@ func NewRtdtManager() *RtdtManager {
 	return &rMan
 }
 
-// When realnet is clab venv, use this to create it
+// When realnet is supposed to be based on containerlab virtual environment, use this to create it
 func (r *RtdtManager) LaunchRealnetVEnv(realnetName string, sdnConfig *sdnconfig.SdnConfig, baseClabConfig *clabconfig.ClabConfig) error {
 	r.baseClabConfig = baseClabConfig
 	var realnetClabFName string
+
 	// Generate a clabconfig file based on the base config and sdnconfig
 	realnetClab, err := r.ProduceClabConfig(realnetName, r.baseClabConfig, sdnConfig)
 	if err != nil {
 		return fmt.Errorf("Error in LaunchRealnet(): %w", err)
 	}
 	fmt.Println("Produced realnet ClabConfig file from sdnconfig and base config")
-	// Need to write the clab struct to disk
+	// Need to write the clab struct to disk:
 	realnetClabPath, err := clabconfig.ClabConfigPath()
 	if err != nil {
 		return fmt.Errorf("Error in LaunchRealnet() %w", err)
@@ -66,17 +67,37 @@ func (r *RtdtManager) LaunchRealnetVEnv(realnetName string, sdnConfig *sdnconfig
 		fmt.Println("Successfully wrote realnet clab config file")
 	}
 
-	fmt.Printf("Trying to now create realnet with fname: %s -------------\n", realnetClabFName)
-	// NewVEnv tasks: deploy the given clab config,
-	r.realnet = venv.NewVEnv(realnetName, realnetClabFName, "admin", "TestPassword", &r.waitGroup)
+	fmt.Printf("Now trying to create realnet with config file: %s\n", realnetClabFName)
+	// NewVEnv tasks:
+	// - deploy the given clab config,
+	// - establish connection to it
+	// - get pnd
+	// - log in
+	// - save everything in VEnv struct
+	r.realnet = venv.NewVEnv(realnetName, realnetClabFName, "admin", "TestPassword", &r.waitGroup, sdnConfig)
 	if r.realnet == nil {
 		return fmt.Errorf("Error in LaunchRealnet: Couldn't deploy VEnv")
 	}
+	//TODO: REPLACE THIS WITH ApplyConfiguration() ???
+	// Create the devices based on sdn config file
 	err = r.realnet.CreateDevices()
 	if err != nil {
 		fmt.Printf("Error: Couldn't create devices!")
 		return err
 	}
+	// Apply the topology based on links in the sdn config file:
+	err = r.realnet.UploadTopology()
+	if err != nil {
+		fmt.Printf("Error occured while trying to upload r.realnet topology to DB: %v\n", err)
+		return err
+	}
+	return fmt.Errorf("--------------------ONLY RUN UNTIL HERE----------------------------")
+
+	// This doesn't work for some reason..
+	// err = r.realnet.ApplyConfiguration(sdnConfig)
+	// if err != nil {
+	// 	fmt.Printf("Failed to apply configuration: %v\n", err)
+	// }
 
 	// Now setup the just-created environment
 	// Need to:
@@ -92,17 +113,11 @@ func (r *RtdtManager) LaunchRealnetVEnv(realnetName string, sdnConfig *sdnconfig
 		fmt.Printf("Error: Couldnt upload clab config: %v\n", err)
 		return err
 	}
-	err = r.realnet.RetrieveClabConfig()
-	if err != nil {
-		fmt.Printf("Error: Couldn't retrieve clab config: %v\n", err)
-		return err
-	}
-
-	err = r.realnet.UploadTopology()
-	if err != nil {
-		fmt.Printf("Error occured while trying to upload r.realnet topology to DB: %v\n", err)
-		return err
-	}
+	// err = r.realnet.RetrieveClabConfig()
+	// if err != nil {
+	// 	fmt.Printf("Error: Couldn't retrieve clab config: %v\n", err)
+	// 	return err
+	// }
 
 	return nil
 }
@@ -214,7 +229,7 @@ func (r *RtdtManager) LaunchTwin(twinSubnetIPv4, twinSubnetIPv6, twinName string
 		return fmt.Errorf("Failed to write modified twin clab config to disk: %w", err)
 	}
 
-	twin := venv.NewVEnv(twinName, twinClabFName, "admin", "TestPassword", &r.waitGroup)
+	twin := venv.NewVEnv(twinName, twinClabFName, "admin", "TestPassword", &r.waitGroup, nil)
 	r.rtdt_twins = append(r.rtdt_twins, twin)
 	return nil
 }
@@ -305,7 +320,7 @@ func (r *RtdtManager) Run() error {
 
 // Receive events from realnet VEnv
 func (r *RtdtManager) InitEventSystem() error {
-    fmt.Println("Starting Event System for realnet!")
+	fmt.Println("Starting Event System for realnet!")
 	realnet_auth := r.realnet.GetAuth()
 	ctx := realnet_auth.CreateContextWithAuthorization()
 	queueCredentials, err := registration.Register(ctx, realnet_auth.GetAddress(), "basic-interface-monitoring", "SecurePresharedToken")
diff --git a/applications/rtdt-manager/sdnconfig/sdnconfig.go b/applications/rtdt-manager/sdnconfig/sdnconfig.go
index a6a64bd3fe2fd9ccc4d5d9646e60b977ea3f4f9e..30077b39d2aef2bd9c16fe0a283402f7dc15c490 100644
--- a/applications/rtdt-manager/sdnconfig/sdnconfig.go
+++ b/applications/rtdt-manager/sdnconfig/sdnconfig.go
@@ -8,6 +8,8 @@ import (
 	"time"
 
 	configPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement"
+	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/conflict"
+	topoPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology"
 	rtdt_auth "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/rtdt-auth"
 	"code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util"
 )
@@ -24,6 +26,7 @@ type Metadata struct {
 	CreatedAt   time.Time `json:"created_at"`
 	LastUpdated time.Time `json:"last_updated"`
 }
+
 type NetworkElement struct {
 	ID                string `json:"id"`
 	Name              string `json:"name"`
@@ -67,15 +70,16 @@ type Port struct {
 }
 
 // this is needed because port in link differs from port in port-store (configuration field)
+// TODO Does this still apply?
 type LinkPort struct {
-	ID            string     `json:"id"`
-	Name          string     `json:"name"`
-	Metadata      Metadata   `json:"metadata"`
-	Configuration PortConfig `json:"configuration"`
+	ID            string     `json:"Id"`
+	Name          string     `json:"Name"`
+	Metadata      Metadata   `json:"Metadata"`
+	Configuration PortConfig `json:"Configuration"`
 }
 type PortConfig struct {
-	IP           string `json:"ip"`
-	PrefixLength int    `json:"prefix_length"`
+	IP           string `json:"Ip"`
+	PrefixLength int64  `json:"PrefixLength"`
 }
 
 func NewSdnConfig() *SdnConfig {
@@ -104,6 +108,14 @@ func (s *SdnConfig) LoadSdnConfig(configFilename string) error {
 	if err != nil {
 		return fmt.Errorf("Error in LoadSdnConfig(): %w", err)
 	}
+
+	jsonData, err := json.MarshalIndent(s, "", "  ")
+	if err != nil {
+		return fmt.Errorf("Error marshalling struct to JSON: %w", err)
+	}
+	fmt.Println("------- SDNCONFIG ------------")
+	fmt.Println(string(jsonData))
+	fmt.Println("------- SDNCONFIG ------------")
 	return nil
 }
 
@@ -167,3 +179,41 @@ func (s *SdnConfig) GetMneByID(ID string) *NetworkElement {
 	}
 	return nil
 }
+
+func (n *Node) Convert() *topoPb.Node {
+	return &topoPb.Node{
+		Id:       n.ID,
+		Name:     n.Name,
+		Metadata: &conflict.Metadata{},
+	}
+}
+
+func (p *LinkPort) Convert() *topoPb.Port {
+	return &topoPb.Port{
+		Id:   p.ID,
+		Name: p.Name,
+		Configuration: &topoPb.Configuration{
+			Ip:           p.Configuration.IP,
+			PrefixLength: p.Configuration.PrefixLength,
+		},
+		Metadata: &conflict.Metadata{},
+	}
+}
+func (p *Port) Convert() *topoPb.Port {
+	return &topoPb.Port{
+		Id:            p.ID,
+		Name:          p.Name,
+		Configuration: &topoPb.Configuration{},
+	}
+}
+
+func (l *Link) Convert() *topoPb.Link {
+	return &topoPb.Link{
+		Id:         l.ID,
+		Name:       l.Name,
+		SourceNode: l.SourceNode.Convert(),
+		SourcePort: l.SourcePort.Convert(),
+		TargetNode: l.TargetNode.Convert(),
+		TargetPort: l.TargetPort.Convert(),
+	}
+}
diff --git a/applications/rtdt-manager/test-config/downloaded-config.json b/applications/rtdt-manager/test-config/downloaded-config.json
new file mode 100644
index 0000000000000000000000000000000000000000..99af02e721055ac04fdf4c5459274198d7abc009
--- /dev/null
+++ b/applications/rtdt-manager/test-config/downloaded-config.json
@@ -0,0 +1,266 @@
+ {
+  "pndID": "5f20f34b-cbd0-4511-9ddc-c50cf6a3b49d",
+  "nodes": [
+    {
+      "id": "db563e8d-0755-4df7-8458-56e3242b1cd4",
+      "name": "gnmi-target-switch0",
+      "metadata": {
+        "created_at": "2025-02-26T11:01:02.974Z",
+        "last_updated": "2025-02-26T11:01:02.974Z"
+      }
+    },
+    {
+      "id": "f14ccc06-0143-4196-9aba-7812fae01d11",
+      "name": "gnmi-target-switch1",
+      "metadata": {
+        "created_at": "2025-02-26T11:01:02.992Z",
+        "last_updated": "2025-02-26T11:01:02.992Z"
+      }
+    },
+    {
+      "id": "c1012f26-99ef-41d0-970b-4642012ebace",
+      "name": "centos0",
+      "metadata": {
+        "created_at": "2025-02-26T11:01:03.001Z",
+        "last_updated": "2025-02-26T11:01:03.001Z"
+      }
+    },
+    {
+      "id": "15f1104a-26a7-49e9-ba57-9eed8720e3ad",
+      "name": "centos1",
+      "metadata": {
+        "created_at": "2025-02-26T11:01:03.004Z",
+        "last_updated": "2025-02-26T11:01:03.004Z"
+      }
+    }
+  ],
+  "ports": [
+    {
+      "id": "1950bf78-2fe3-4e0f-a4a6-9c42c660fb36",
+      "name": "eth1",
+      "metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "configuration": ""
+    },
+    {
+      "id": "b0338d9a-50e4-477f-bb30-18ad3c61302f",
+      "name": "eth1",
+      "metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "configuration": ""
+    },
+    {
+      "id": "df55cdb4-aa55-495c-8e27-245e6ed6b806",
+      "name": "eth2",
+      "metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "configuration": ""
+    },
+    {
+      "id": "505f067f-62a4-484e-9f06-673f668a1908",
+      "name": "eth1",
+      "metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "configuration": ""
+    },
+    {
+      "id": "164c384d-7179-42c9-8c54-4d1ad148b7b8",
+      "name": "eth2",
+      "metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "configuration": ""
+    },
+    {
+      "id": "b279ea32-fa61-4167-93aa-54afe45cfdb0",
+      "name": "eth1",
+      "metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "configuration": ""
+    }
+  ],
+  "links": [
+    {
+      "ID": "b482a038-6e38-4dc5-906b-fd31abdbb23e",
+      "Metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "Name": "gnmi-target-switch0:gnmi-target-switch1",
+      "SourceNode": {
+        "id": "db563e8d-0755-4df7-8458-56e3242b1cd4",
+        "name": "gnmi-target-switch0",
+        "metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        }
+      },
+      "SourcePort": {
+        "Id": "1950bf78-2fe3-4e0f-a4a6-9c42c660fb36",
+        "Name": "eth1",
+        "Metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        },
+        "Configuration": {
+          "Ip": "192.168.178.2",
+          "PrefixLength": 24
+        }
+      },
+      "TargetNode": {
+        "id": "f14ccc06-0143-4196-9aba-7812fae01d11",
+        "name": "gnmi-target-switch1",
+        "metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        }
+      },
+      "TargetPort": {
+        "Id": "b0338d9a-50e4-477f-bb30-18ad3c61302f",
+        "Name": "eth1",
+        "Metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        },
+        "Configuration": {
+          "Ip": "192.168.178.3",
+          "PrefixLength": 24
+        }
+      }
+    },
+    {
+      "ID": "0bee4805-4a96-4870-9b4a-c0742f58d3e8",
+      "Metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "Name": "gnmi-target-switch0:centos0",
+      "SourceNode": {
+        "id": "db563e8d-0755-4df7-8458-56e3242b1cd4",
+        "name": "gnmi-target-switch0",
+        "metadata": {
+          "created_at": "2025-02-26T11:01:02.974Z",
+          "last_updated": "2025-02-26T11:01:02.974Z"
+        }
+      },
+      "SourcePort": {
+        "Id": "df55cdb4-aa55-495c-8e27-245e6ed6b806",
+        "Name": "eth2",
+        "Metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        },
+        "Configuration": {
+          "Ip": "192.168.178.2",
+          "PrefixLength": 24
+        }
+      },
+      "TargetNode": {
+        "id": "c1012f26-99ef-41d0-970b-4642012ebace",
+        "name": "centos0",
+        "metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        }
+      },
+      "TargetPort": {
+        "Id": "505f067f-62a4-484e-9f06-673f668a1908",
+        "Name": "eth1",
+        "Metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        },
+        "Configuration": {
+          "Ip": "192.168.178.3",
+          "PrefixLength": 24
+        }
+      }
+    },
+    {
+      "ID": "4fcd6017-dbf2-471b-bf03-42f73b993676",
+      "Metadata": {
+        "created_at": "0001-01-01T00:00:00Z",
+        "last_updated": "0001-01-01T00:00:00Z"
+      },
+      "Name": "gnmi-target-switch1:centos1",
+      "SourceNode": {
+        "id": "f14ccc06-0143-4196-9aba-7812fae01d11",
+        "name": "gnmi-target-switch1",
+        "metadata": {
+          "created_at": "2025-02-26T11:01:02.992Z",
+          "last_updated": "2025-02-26T11:01:02.992Z"
+        }
+      },
+      "SourcePort": {
+        "Id": "164c384d-7179-42c9-8c54-4d1ad148b7b8",
+        "Name": "eth2",
+        "Metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        },
+        "Configuration": {
+          "Ip": "192.168.178.2",
+          "PrefixLength": 24
+        }
+      },
+      "TargetNode": {
+        "id": "15f1104a-26a7-49e9-ba57-9eed8720e3ad",
+        "name": "centos1",
+        "metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        }
+      },
+      "TargetPort": {
+        "Id": "b279ea32-fa61-4167-93aa-54afe45cfdb0",
+        "Name": "eth1",
+        "Metadata": {
+          "created_at": "0001-01-01T00:00:00Z",
+          "last_updated": "0001-01-01T00:00:00Z"
+        },
+        "Configuration": {
+          "Ip": "192.168.178.3",
+          "PrefixLength": 24
+        }
+      }
+    }
+  ],
+  "plugins": null,
+  "networkelements": [
+    {
+      "id": "db563e8d-0755-4df7-8458-56e3242b1cd4",
+      "name": "gnmi-target-switch0",
+      "transport_type": "gnmi",
+      "transport_address": "172.100.0.11:7030",
+      "transport_username": "admin",
+      "transport_password": "admin",
+      "transport_tls": true,
+      "plugin": "2455b300-67ee-4695-95cd-1c7a8e6e28ab",
+      "model": "{\"openconfig-interfaces:interfaces\":{\"interface\":[{\"config\":{\"enabled\":true,\"mtu\":1500,\"name\":\"eth0\"},\"name\":\"eth0\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":787,\"loopback-mode\":false,\"oper-status\":\"UP\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv4\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"172.100.0.11\",\"prefix-length\":16},\"ip\":\"172.100.0.11\"}]}},\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"2001:db8::9\",\"prefix-length\":64},\"ip\":\"2001:db8::9\"}]}}},{\"config\":{\"index\":1},\"index\":1,\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"fe80::42:acff:fe64:b\",\"prefix-length\":64},\"ip\":\"fe80::42:acff:fe64:b\"}]}}}]}},{\"config\":{\"enabled\":true,\"mtu\":9500,\"name\":\"eth1\"},\"name\":\"eth1\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":792,\"loopback-mode\":false,\"oper-status\":\"UP\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"fe80::a8c1:abff:fe36:5da3\",\"prefix-length\":64},\"ip\":\"fe80::a8c1:abff:fe36:5da3\"}]}}}]}},{\"config\":{\"enabled\":true,\"mtu\":9500,\"name\":\"eth2\"},\"name\":\"eth2\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":783,\"loopback-mode\":false,\"oper-status\":\"UP\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"fe80::a8c1:abff:fec9:790c\",\"prefix-length\":64},\"ip\":\"fe80::a8c1:abff:fec9:790c\"}]}}}]}},{\"config\":{\"enabled\":false,\"mtu\":0,\"name\":\"lo\"},\"name\":\"lo\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":1,\"loopback-mode\":true,\"oper-status\":\"UNKNOWN\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv4\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"127.0.0.1\",\"prefix-length\":8},\"ip\":\"127.0.0.1\"}]}},\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"::1\",\"prefix-length\":128},\"ip\":\"::1\"}]}}}]}}]},\"openconfig-network-instance:network-instances\":{\"network-instance\":[{\"config\":{\"name\":\"DEFAULT\"},\"name\":\"DEFAULT\",\"protocols\":{\"protocol\":[{\"config\":{\"identifier\":\"openconfig-policy-types:STATIC\",\"name\":\"STATIC\"},\"identifier\":\"openconfig-policy-types:STATIC\",\"name\":\"STATIC\",\"static-routes\":{\"static\":[{\"config\":{\"prefix\":\"0.0.0.0/0\"},\"next-hops\":{\"next-hop\":[{\"config\":{\"index\":\"AUTO_172.100.0.1\",\"next-hop\":\"172.100.0.1\"},\"index\":\"AUTO_172.100.0.1\",\"interface-ref\":{\"config\":{\"interface\":\"eth0\"}}}]},\"prefix\":\"0.0.0.0/0\"},{\"config\":{\"prefix\":\"::/0\"},\"next-hops\":{\"next-hop\":[{\"config\":{\"index\":\"AUTO_2001:db8::1\",\"next-hop\":\"2001:db8::1\"},\"index\":\"AUTO_2001:db8::1\",\"interface-ref\":{\"config\":{\"interface\":\"eth0\"}}}]},\"prefix\":\"::/0\"}]}}]}}]},\"openconfig-system:system\":{\"clock\":{\"config\":{\"timezone-name\":\"UTC\"}},\"config\":{\"domain-name\":\"Not.implemented.yet\",\"hostname\":\"gnmi-target-switch0\",\"motd-banner\":\"\\nThe programs included with the Debian GNU/Linux system are free software;\\nthe exact distribution terms for each program are described in the\\nindividual files in /usr/share/doc/*/copyright.\\n\\nDebian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent\\npermitted by applicable law.\\n\"},\"memory\":{\"state\":{\"free\":\"6650664\",\"physical\":\"63586184\",\"used\":\"56935520\"}},\"state\":{\"boot-time\":\"1740042208\",\"current-datetime\":\"2025-02-26T11:00:46Z\",\"software-version\":\"debian:12\"}}}",
+      "pnd_id": "5f20f34b-cbd0-4511-9ddc-c50cf6a3b49d"
+    },
+    {
+      "id": "f14ccc06-0143-4196-9aba-7812fae01d11",
+      "name": "gnmi-target-switch1",
+      "transport_type": "gnmi",
+      "transport_address": "172.100.0.12:7030",
+      "transport_username": "admin",
+      "transport_password": "admin",
+      "transport_tls": true,
+      "plugin": "3de782ef-e51b-472c-a0fb-8ba48768e7ac",
+      "model": "{\"openconfig-interfaces:interfaces\":{\"interface\":[{\"config\":{\"enabled\":true,\"mtu\":1500,\"name\":\"eth0\"},\"name\":\"eth0\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":789,\"loopback-mode\":false,\"oper-status\":\"UP\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv4\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"172.100.0.12\",\"prefix-length\":16},\"ip\":\"172.100.0.12\"}]}},\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"2001:db8::a\",\"prefix-length\":64},\"ip\":\"2001:db8::a\"}]}}},{\"config\":{\"index\":1},\"index\":1,\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"fe80::42:acff:fe64:c\",\"prefix-length\":64},\"ip\":\"fe80::42:acff:fe64:c\"}]}}}]}},{\"config\":{\"enabled\":true,\"mtu\":9500,\"name\":\"eth1\"},\"name\":\"eth1\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":791,\"loopback-mode\":false,\"oper-status\":\"UP\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"fe80::a8c1:abff:fe7d:5116\",\"prefix-length\":64},\"ip\":\"fe80::a8c1:abff:fe7d:5116\"}]}}}]}},{\"config\":{\"enabled\":true,\"mtu\":9500,\"name\":\"eth2\"},\"name\":\"eth2\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":785,\"loopback-mode\":false,\"oper-status\":\"UP\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"fe80::a8c1:abff:fe4f:65ae\",\"prefix-length\":64},\"ip\":\"fe80::a8c1:abff:fe4f:65ae\"}]}}}]}},{\"config\":{\"enabled\":false,\"mtu\":0,\"name\":\"lo\"},\"name\":\"lo\",\"state\":{\"admin-status\":\"UP\",\"ifindex\":1,\"loopback-mode\":true,\"oper-status\":\"UNKNOWN\"},\"subinterfaces\":{\"subinterface\":[{\"config\":{\"index\":0},\"index\":0,\"openconfig-if-ip:ipv4\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"127.0.0.1\",\"prefix-length\":8},\"ip\":\"127.0.0.1\"}]}},\"openconfig-if-ip:ipv6\":{\"addresses\":{\"address\":[{\"config\":{\"ip\":\"::1\",\"prefix-length\":128},\"ip\":\"::1\"}]}}}]}}]},\"openconfig-network-instance:network-instances\":{\"network-instance\":[{\"config\":{\"name\":\"DEFAULT\"},\"name\":\"DEFAULT\",\"protocols\":{\"protocol\":[{\"config\":{\"identifier\":\"openconfig-policy-types:STATIC\",\"name\":\"STATIC\"},\"identifier\":\"openconfig-policy-types:STATIC\",\"name\":\"STATIC\",\"static-routes\":{\"static\":[{\"config\":{\"prefix\":\"0.0.0.0/0\"},\"next-hops\":{\"next-hop\":[{\"config\":{\"index\":\"AUTO_172.100.0.1\",\"next-hop\":\"172.100.0.1\"},\"index\":\"AUTO_172.100.0.1\",\"interface-ref\":{\"config\":{\"interface\":\"eth0\"}}}]},\"prefix\":\"0.0.0.0/0\"},{\"config\":{\"prefix\":\"::/0\"},\"next-hops\":{\"next-hop\":[{\"config\":{\"index\":\"AUTO_2001:db8::1\",\"next-hop\":\"2001:db8::1\"},\"index\":\"AUTO_2001:db8::1\",\"interface-ref\":{\"config\":{\"interface\":\"eth0\"}}}]},\"prefix\":\"::/0\"}]}}]}}]},\"openconfig-system:system\":{\"clock\":{\"config\":{\"timezone-name\":\"UTC\"}},\"config\":{\"domain-name\":\"Not.implemented.yet\",\"hostname\":\"gnmi-target-switch1\",\"motd-banner\":\"\\nThe programs included with the Debian GNU/Linux system are free software;\\nthe exact distribution terms for each program are described in the\\nindividual files in /usr/share/doc/*/copyright.\\n\\nDebian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent\\npermitted by applicable law.\\n\"},\"memory\":{\"state\":{\"free\":\"6650664\",\"physical\":\"63586184\",\"used\":\"56935520\"}},\"state\":{\"boot-time\":\"1740042208\",\"current-datetime\":\"2025-02-26T11:00:46Z\",\"software-version\":\"debian:12\"}}}",
+      "pnd_id": "5f20f34b-cbd0-4511-9ddc-c50cf6a3b49d"
+    }
+  ]
+}
diff --git a/applications/rtdt-manager/test-config/main.go b/applications/rtdt-manager/test-config/main.go
index 8f6dc11cf1c7fa4714620d5a353e0d454448408a..6e5386b026ac9008f94fb03e6bcdd13638e8af42 100644
--- a/applications/rtdt-manager/test-config/main.go
+++ b/applications/rtdt-manager/test-config/main.go
@@ -15,26 +15,12 @@ import (
 	"google.golang.org/grpc/credentials/insecure"
 )
 
-// This is for testing sdnconfig files
-func main() {
-	var sdnConfigPath string
-	flag.StringVar(&sdnConfigPath, "sdnconfig", "applications/rtdt-manager/data/sample_venv_sdnconfig.json", "SdnConfig file (json)")
-	flag.Parse()
-	fmt.Println("sdnConfigPath:", sdnConfigPath)
-	// load the test config, upload to db
-	testconfig := sdnconfig.NewSdnConfig()
-	wd, err := os.Getwd()
-	fmt.Println("Getwd returns:", wd)
-	err = testconfig.LoadSdnConfig(sdnConfigPath)
-	if err != nil {
-		fmt.Println("Couldn't load config, err:", err)
-		return
-	}
+func SetupGosdnConn() (*pnd.PrincipalNetworkDomain, *rtdt_auth.RtdtAuth) {
 	dialOption := grpc.WithTransportCredentials(insecure.NewCredentials())
 	conn, err := grpc.NewClient("172.100.0.5:55055", dialOption, grpc.WithDefaultCallOptions())
 	if err != nil {
 		fmt.Printf("Error: Failed to create connection to gosdn: %v\n", err)
-		return
+		return nil, nil
 	} else {
 		fmt.Printf("Successfully created connection to gosdn\n")
 	}
@@ -49,25 +35,66 @@ func main() {
 		fmt.Printf("Couldn't retrieve PND, retrying in 2 seconds..\n")
 		time.Sleep(time.Second * 2)
 	}
-	testdata, err := json.Marshal(testconfig)
+	return gosdn_pnd, testauth
+
+}
+
+func Download() {
+	gosdn_pnd, testauth := SetupGosdnConn()
+	if gosdn_pnd == nil || testauth == nil {
+		fmt.Println("ERROR: couldn't establish connection to gosdn")
+	}
+	newconfig := sdnconfig.NewSdnConfig()
+	newconfig.RetrieveSdnConfig(gosdn_pnd.Id, *testauth)
+
+	data, err := json.MarshalIndent(newconfig, "", "  ")
 	if err != nil {
 		fmt.Println("Failed to marshall data")
 		return
 	}
-	fmt.Println("Data to be uploaded:", string(testdata))
 
-	testconfig.UploadSdnConfig(gosdn_pnd.Id, *testauth)
-	fmt.Println("Successully uploaded config.. waiting..")
-	time.Sleep(time.Second * 2)
-	newconfig := sdnconfig.NewSdnConfig()
-	newconfig.RetrieveSdnConfig(gosdn_pnd.Id, *testauth)
+	fmt.Println("Successully downloaded config:", string(data))
+}
 
-	data, err := json.Marshal(newconfig)
+func Upload(sdnConfigPath string) {
+	gosdn_pnd, testauth := SetupGosdnConn()
+	testconfig := sdnconfig.NewSdnConfig()
+	wd, err := os.Getwd()
+	fmt.Println("Getwd returns:", wd)
+	err = testconfig.LoadSdnConfig(sdnConfigPath)
+	if err != nil {
+		fmt.Println("Couldn't load config, err:", err)
+	}
+	testdata, err := json.Marshal(testconfig)
 	if err != nil {
 		fmt.Println("Failed to marshall data")
 		return
 	}
+	fmt.Println("Data to be uploaded:", string(testdata))
 
-	fmt.Println("Successully downloaded config:", string(data))
+	testconfig.UploadSdnConfig(gosdn_pnd.Id, *testauth)
 
 }
+
+// This is for testing sdnconfig files
+func main() {
+	var sdnConfigPath string
+	var mode string
+	flag.StringVar(&mode, "mode", "download", "Whether to download config or upload config")
+	flag.StringVar(&sdnConfigPath, "sdnconfig", "applications/rtdt-manager/data/sample_venv_sdnconfig.json", "SdnConfig file (json)")
+	flag.Parse()
+
+	switch mode {
+	case "download":
+		fmt.Println("Mode: Download")
+		Download()
+		return
+	case "upload":
+		fmt.Println("Mode: Upload")
+		Upload(sdnConfigPath)
+		return
+	default:
+		fmt.Println("Unknown Mode!")
+		return
+	}
+}
diff --git a/applications/rtdt-manager/venv/venv.go b/applications/rtdt-manager/venv/venv.go
index 88b0540fc2e040e513892d306b962892bd2137d4..7fffc7eeadc60e670998e1df167f605b590b4247 100644
--- a/applications/rtdt-manager/venv/venv.go
+++ b/applications/rtdt-manager/venv/venv.go
@@ -10,6 +10,7 @@ import (
 	"time"
 
 	configPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement"
+	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/conflict"
 	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
 	"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	topoPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology"
@@ -37,7 +38,7 @@ type VEnv struct {
 	conn                 *grpc.ClientConn // The connection to this specific environment's gosdn
 	pnd                  *pnd.PrincipalNetworkDomain
 	clabData             *clabconfig.ClabConfig // Represents yaml file that was used to deploy
-	sdnConfig            sdnconfig.SdnConfig   // Represents json config file for configuration grpc interface
+	sdnConfig            *sdnconfig.SdnConfig   // Represents json config file for configuration grpc interface
 	topology             *rtdt_topology.Topology
 	clabFilename         string // This is the name of the yaml file clabData is based on
 	StopChan             <-chan struct{}
@@ -49,7 +50,7 @@ type VEnv struct {
 // Accepts a yaml filename to deploy a container lab environment
 // TODO Split up into sub-functions
 // This takes FULL path name to clab config
-func NewVEnv(name, clabFilename, user, pass string, wg *sync.WaitGroup) *VEnv {
+func NewVEnv(name, clabFilename, user, pass string, wg *sync.WaitGroup, sdnConfig *sdnconfig.SdnConfig) *VEnv {
 	fmt.Printf("[%s] - Creating new virtual environment\n", name)
 	wg.Add(1) // Register the venv and run atleast until it calls wg.Done()
 	var err error
@@ -117,11 +118,34 @@ func NewVEnv(name, clabFilename, user, pass string, wg *sync.WaitGroup) *VEnv {
 		clabData:             clabData,
 		clabFilename:         clabFilename,
 		waitGroup:            wg,
-		topology:             nil,                                            // set this later
-		containerRegistryURL: "registry.code.fbi.h-da.de/danet/gnmi-target/", // TODO: Could let user choose
+		topology:             nil, // set this later
+		sdnConfig:            sdnConfig,
+		containerRegistryURL: "registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test", // TODO: Could let user choose
 	}
 }
 
+func (v *VEnv) ApplyConfiguration(sdnConfig *sdnconfig.SdnConfig) error {
+	v.sdnConfig = sdnConfig
+	sdnConfigParsed, err := json.Marshal(v.sdnConfig)
+	if err != nil {
+		fmt.Println("PARSING ERROR")
+		return err
+	}
+	configService := configPb.NewConfigurationManagementServiceClient(v.auth.GetConn())
+	request := &configPb.ImportSDNConfigRequest{
+		Timestamp:     util.Now(),
+		Pid:           v.pnd.Id,
+		SdnConfigData: string(sdnConfigParsed),
+	}
+	response, err := configService.ImportSDNConfig(v.auth.CreateContextWithAuthorization(), request)
+	if err != nil {
+		fmt.Println("RESPONSE ERROR")
+		return err
+	}
+	fmt.Println("Configuration Response:", response.String())
+	return nil
+}
+
 // Based on saved sdnconfig, create devices
 func (v *VEnv) CreateDevices() error {
 	// Alternative (better) approach
@@ -300,24 +324,27 @@ func (v *VEnv) ApplyRoutes() error {
 func (v *VEnv) UploadTopology() error {
 	conn := v.auth.GetConn()
 	topoService := topoPb.NewTopologyServiceClient(conn)
-	for _, link := range v.topology.Links {
-		ctx := v.auth.CreateContextWithAuthorization()
-
-		l := link.Convert()
-		l.Name = l.SourceNode.Name + ":" + l.TargetNode.Name
-		l.SourcePort.Configuration = &topoPb.Configuration{Ip: "192.168.178.2", PrefixLength: 24}
-		l.TargetPort.Configuration = &topoPb.Configuration{Ip: "192.168.178.3", PrefixLength: 24}
 
-		addLinkRequest := &topoPb.AddLinkRequest{
+	for _, link := range v.sdnConfig.Links {
+		req := &topoPb.AddLinkRequest{
 			Timestamp: util.Now(),
-			Link:      l,
+			Link: &topoPb.Link{
+				Id:         link.ID,
+				Name:       link.Name,
+				SourceNode: link.SourceNode.Convert(),
+				SourcePort: link.SourcePort.Convert(),
+				TargetNode: link.TargetNode.Convert(),
+				TargetPort: link.TargetPort.Convert(),
+				Metadata:   &conflict.Metadata{},
+			},
 		}
-		fmt.Println("AddLink is:", addLinkRequest.String())
-		topoResponse, err := topoService.AddLink(ctx, addLinkRequest)
+		//fmt.Println("AddLink is:", req.String())
+		ctx := v.auth.CreateContextWithAuthorization()
+		topoResponse, err := topoService.AddLink(ctx, req)
 		if err != nil {
 			return err
 		}
-		fmt.Printf("Successfully uploaded Link to DB: %s\n", topoResponse.String())
+		fmt.Printf("Successfully uploaded topo link to DB: %s\n", topoResponse.String())
 	}
 	return nil
 }