diff --git a/src/kubernetes-api/api/v1/networkedgedevice_types.go b/src/kubernetes-api/api/v1/networkedgedevice_types.go
index db1ed30b2f1e209c8a53634a08a38b317dd4371a..8ce50c4f8caea6b27317c99fe8713eb99cca6fe6 100644
--- a/src/kubernetes-api/api/v1/networkedgedevice_types.go
+++ b/src/kubernetes-api/api/v1/networkedgedevice_types.go
@@ -99,6 +99,12 @@ type SwitchTemplateSpec struct {
 	Spec SwitchPodSpec `json:"spec,omitempty"`
 }
 
+type NodeConfigSpec struct {
+	NodeName string `json:"nodeName"`
+
+	IPAddress string `json:"ipAddress"`
+}
+
 // NetworkEdgeDeviceSpec defines the desired state of NetworkEdgeDevice
 type NetworkEdgeDeviceSpec struct {
 	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
@@ -107,6 +113,9 @@ type NetworkEdgeDeviceSpec struct {
 	// The SDN Controller that manages the overlay network. Must specify a domain and a name.
 	NetworkController *NetworkControllerSpec `json:"networkController"`
 
+	// Node Configuration
+	NodeConfig *NodeConfigSpec `json:"nodeConfig"`
+
 	// Field exclusive to the multi-domain overlay type. If specified in other  types of overlays, the reosurce will launch an error and won't be created.
 	Neighbors []NeighborSpec `json:"neighbors,omitempty"`
 
diff --git a/src/kubernetes-api/internal/controller/networkedgedevice_controller.go b/src/kubernetes-api/internal/controller/networkedgedevice_controller.go
index ad1a673001e8f82eed9818aa785d7a97dd64e86b..0a25f0c2981f6b0c540a455dfbe426d33c5f9f40 100644
--- a/src/kubernetes-api/internal/controller/networkedgedevice_controller.go
+++ b/src/kubernetes-api/internal/controller/networkedgedevice_controller.go
@@ -32,6 +32,8 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
+	nedv1 "l2sm.local/ovs-switch/api/v1"
 )
 
 // NetworkEdgeDeviceReconciler reconciles a NetworkEdgeDevice object
@@ -162,23 +164,30 @@ func (r *NetworkEdgeDeviceReconciler) deleteExternalResources(ctx context.Contex
 	return nil
 }
 func (r *NetworkEdgeDeviceReconciler) createExternalResources(ctx context.Context, netEdgeDevice *l2smv1.NetworkEdgeDevice) error {
-	// Convert netEdgeDevice.Spec.Neighbors to JSON
-	neighborsJSON, err := json.Marshal(netEdgeDevice.Spec.Neighbors)
+
+	neighbors := []string{}
+	nedNeighbors, err := json.Marshal(nedv1.Node{Name: netEdgeDevice.Spec.NodeConfig.NodeName, NodeIP: netEdgeDevice.Spec.NodeConfig.IPAddress, NeighborNodes: neighbors})
 	if err != nil {
 		return err
 	}
+	nedName := fmt.Sprintf("%s-%s", netEdgeDevice.Spec.NodeConfig.NodeName, netEdgeDevice.Spec.NetworkController.Name)
 
+	nedConfig, err := json.Marshal(nedv1.NedSettings{ControllerIP: netEdgeDevice.Spec.NetworkController.Domain, NodeName: netEdgeDevice.Spec.NodeConfig.NodeName, NedName: nedName})
+	if err != nil {
+		return err
+	}
 	// Create a ConfigMap to store the neighbors JSON
 
 	constructConfigMapForNED := func(netEdgeDevice *l2smv1.NetworkEdgeDevice) (*corev1.ConfigMap, error) {
 
 		configMap := &corev1.ConfigMap{
 			ObjectMeta: metav1.ObjectMeta{
-				Name:      fmt.Sprintf("%s-neighbors", netEdgeDevice.Name),
+				Name:      fmt.Sprintf("%s-config", netEdgeDevice.Name),
 				Namespace: netEdgeDevice.Namespace,
 			},
 			Data: map[string]string{
-				"neighbors.json": string(neighborsJSON),
+				"neighbors.json": string(nedNeighbors),
+				"config.json":    string(nedConfig),
 			},
 		}
 		if err := controllerutil.SetControllerReference(netEdgeDevice, configMap, r.Scheme); err != nil {
diff --git a/src/kubernetes-api/internal/controller/pod_controller.go b/src/kubernetes-api/internal/controller/pod_controller.go
index 18897347f9f70e1611527a9b399add7bfd0506f5..34adae6ba1b4e85abdcc11f37ff3d005851ce10a 100644
--- a/src/kubernetes-api/internal/controller/pod_controller.go
+++ b/src/kubernetes-api/internal/controller/pod_controller.go
@@ -32,6 +32,8 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/log"
+
+	nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
 )
 
 // PodReconciler reconciles a Pod object
@@ -75,7 +77,7 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 
 	// Ensure the Multus annotation is correctly formatted and present
 
-	// Check if the object is being deleted
+	// Check if the pod is being deleted
 	if pod.GetDeletionTimestamp() != nil {
 		if utils.ContainsString(pod.GetFinalizers(), l2smFinalizer) {
 			logger.Info("L2S-M Pod deleted: detaching l2network")
@@ -118,8 +120,8 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 		return ctrl.Result{}, nil
 	}
 
-	// If it's not getting deleted, then let's check if it's been created or not
-	// Add finalizer for this CR
+	// Check if the pod has a finalizer attached to it. If not, we asume this pod is being created,
+	// so we attach the l2network to it.
 	if !utils.ContainsString(pod.GetFinalizers(), l2smFinalizer) {
 		// We add the finalizers now that the pod has been added to the network and we want to keep track of it
 		pod.SetFinalizers(append(pod.GetFinalizers(), l2smFinalizer))
@@ -128,12 +130,20 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 		}
 		logger.Info("L2S-M Pod created: attaching to l2network")
 
+		// We extract the network names and ip adresses desired for our pod.
 		networkAnnotations, err := extractNetworks(pod.Annotations[L2SM_NETWORK_ANNOTATION], r.SwitchesNamespace)
 
+		// If there's an error, probably the user did input wrongfully the networks, in this case throw an error.
 		if err != nil {
 			logger.Error(err, "l2 networks could not be extracted from the pods annotations")
+			return ctrl.Result{}, err
 		}
+
+		// We get an array of the existing L2Networks the pod's being associated to.
 		networks, err := GetL2Networks(ctx, r.Client, networkAnnotations)
+
+		// If there's an error, it mayu be that the network is not yet created ornot available. In this case,
+		// we don't let the pod create itself, and wait until the l2network is created and/or available
 		if err != nil {
 
 			logger.Error(nil, "Pod's network annotation incorrect. L2Network not attached.")
@@ -141,6 +151,7 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 			return ctrl.Result{}, err
 
 		}
+
 		// Add the pod interfaces to the sdn controller
 		multusAnnotations, ok := pod.Annotations[MULTUS_ANNOTATION_KEY]
 
@@ -149,19 +160,32 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 			return ctrl.Result{}, nil
 		}
 
+		// We get which interfaces are we using inside the pod, so we can later attach them to the sdn controller
 		multusNetAttachDefinitions, err := extractNetworks(multusAnnotations, r.SwitchesNamespace)
 
+		// If there are not the same number of multus annotations as networks, we need to throw an error as we can't
+		// reach the desired state for the user.
 		if err != nil || len(multusNetAttachDefinitions) != len(networkAnnotations) {
 			logger.Error(nil, "Error detaching the pod from the network attachment definitions")
 			return ctrl.Result{}, nil
 		}
 
+		// Now, for every network, we make a call to the sdn controller, asking for the attachment to the switch
+		// We get the openflow ID of the switch that this pod is connected to.
 		ofID := fmt.Sprintf("of:%s", utils.GenerateDatapathID(pod.Spec.NodeName))
 
 		for index, network := range networks {
-			portNumber, _ := utils.GetPortNumberFromNetAttachDef(multusNetAttachDefinitions[index].Name)
+			// We get the port number based on the name of the multus annotation. veth1 -> port num 1.
+			portNumber, err := utils.GetPortNumberFromNetAttachDef(multusNetAttachDefinitions[index].Name)
+
+			if err != nil {
+				// If there is an error, it must be that the name is not compliant, so we can't be certain of which
+				// port we are trying to attach.
+				return ctrl.Result{}, fmt.Errorf("could not get port number from the multus network annotation: %v. Can't attach pod to network", err)
+			}
 			ofPort := fmt.Sprintf("%s/%s", ofID, portNumber)
 
+			// we inform the sdn controller of this new port attachment
 			err = r.InternalClient.AttachPodToNetwork("vnets", sdnclient.VnetPortPayload{NetworkId: network.Name, Port: []string{ofPort}})
 			if err != nil {
 				logger.Error(err, "Error attaching pod to the l2network")
@@ -172,12 +196,19 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 			// and communicate with it
 			if network.Spec.Provider != nil {
 
-				gatewayNodeName, err := r.CreateNewNEDConnection(network)
+				// First we get information from the NED, required to perform the next operations.
+				// The info we need is the node name it is residing in.
+				nedNodeName := nedinterface.GetNodeName(network.Spec.Provider.Name)
+
+				// Then, we create the connection between the NED and the l2sm-switch, in the internal SDN Controller
+				nedNetworkAttachDef, err := r.ConnectInternalSwitchToNED(ctx, network.Name, nedNodeName)
 				if err != nil {
 					return ctrl.Result{}, nil
 				}
-
-				err = r.ConnectGatewaySwitchToNED(ctx, network.Name, gatewayNodeName)
+				// We attach the ned to this new network, connecting with the IDCO SDN Controller. We need
+				// The Network name so we can know which network to attach the port to.
+				// The multus network attachment definition that will be used as a bridge between the internal switch and the NED.
+				err = r.CreateNewNEDConnection(network, nedNetworkAttachDef.Name, nedNodeName)
 				if err != nil {
 					return ctrl.Result{}, nil
 				}
@@ -191,10 +222,6 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 
 }
 
-// func (r *PodReconciler) GetOpenflowId(ctx context.Context, namespace string) (string,error) {
-// 	return "",nil
-// }
-
 // SetupWithManager sets up the controller with the Manager.
 func (r *PodReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	var err error
@@ -211,63 +238,70 @@ func (r *PodReconciler) SetupWithManager(mgr ctrl.Manager) error {
 		Complete(r)
 }
 
-func (r *PodReconciler) CreateNewNEDConnection(network l2smv1.L2Network) (string, error) {
+// CreateNEDConnection is a method that given the name of the network and the
+func (r *PodReconciler) CreateNewNEDConnection(network l2smv1.L2Network, nedNetworkAttachDef, nedNodeName string) error {
 
 	clientConfig := sdnclient.ClientConfig{BaseURL: fmt.Sprintf("http://%s/onos/v1", network.Spec.Provider.Domain), Username: "karaf", Password: "karaf"}
 
 	externalClient, err := sdnclient.NewClient(sdnclient.InternalType, clientConfig)
 
 	if err != nil {
-		return "", err
-		// logger.Error(err, "no connection could be made with external sdn controller")
+		return fmt.Errorf("no connection could be made with external sdn controller: %s", err)
+
 	}
-	gatewayNodeName, nedPortNumber := nedinterface.GetConnectionInfo()
+	// AddPort returns the port number to attach so we can talk directly with the IDCO
+	// It needs to know which exiting interface to add to the network
+	nedPortNumber, err := nedinterface.AttachInterface(nedNetworkAttachDef)
 
-	nedOFID := fmt.Sprintf("of:%s", utils.GenerateDatapathID(fmt.Sprintf("%s%s", gatewayNodeName, network.Spec.Provider.Name)))
+	if err != nil {
+		return fmt.Errorf("no connection could be made with external sdn controller: %s", err)
+	}
+
+	nedOFID := fmt.Sprintf("of:%s", utils.GenerateDatapathID(fmt.Sprintf("%s-%s", nedNodeName, network.Spec.Provider.Name)))
 	nedOFPort := fmt.Sprintf("%s/%s", nedOFID, nedPortNumber)
 
 	err = externalClient.AttachPodToNetwork("vnets", sdnclient.VnetPortPayload{NetworkId: network.Name, Port: []string{nedOFPort}})
 	if err != nil {
-		return "", errors.Join(err, errors.New("could not update network attachment definition"))
+		return errors.Join(err, errors.New("could not update network attachment definition"))
 
 	}
-	return gatewayNodeName, nil
+	return nil
 }
 
-func (r *PodReconciler) ConnectGatewaySwitchToNED(ctx context.Context, networkName, gatewayNodeName string) error {
+func (r *PodReconciler) ConnectInternalSwitchToNED(ctx context.Context, networkName, nedNodeName string) (nettypes.NetworkAttachmentDefinition, error) {
 
+	// We get a free interface in the node name of the NED, this way we can interconnect the NED with the l2sm switch
 	var err error
-	netAttachDefLabel := NET_ATTACH_LABEL_PREFIX + gatewayNodeName
+	netAttachDefLabel := NET_ATTACH_LABEL_PREFIX + nedNodeName
 	netAttachDefs := GetFreeNetAttachDefs(ctx, r.Client, r.SwitchesNamespace, netAttachDefLabel)
 
 	if len(netAttachDefs.Items) == 0 {
 		err = errors.New("no interfaces available in control plane node")
 		//logger.Error(err, fmt.Sprintf("No interfaces available for node %s", gatewayNodeName))
-		return err
+		return nettypes.NetworkAttachmentDefinition{}, err
 	}
 
 	netAttachDef := &netAttachDefs.Items[0]
 
 	portNumber, _ := utils.GetPortNumberFromNetAttachDef(netAttachDef.Name)
 
-	gatewayOFID := fmt.Sprintf("of:%s", utils.GenerateDatapathID(gatewayNodeName))
+	internalSwitchOFID := fmt.Sprintf("of:%s", utils.GenerateDatapathID(nedNodeName))
 
-	gatewayOFPort := fmt.Sprintf("%s/%s", gatewayOFID, portNumber)
+	internalSwitchOFPort := fmt.Sprintf("%s/%s", internalSwitchOFID, portNumber)
 
-	err = r.InternalClient.AttachPodToNetwork("vnets", sdnclient.VnetPortPayload{NetworkId: networkName, Port: []string{gatewayOFPort}})
+	err = r.InternalClient.AttachPodToNetwork("vnets", sdnclient.VnetPortPayload{NetworkId: networkName, Port: []string{internalSwitchOFPort}})
 
 	if err != nil {
-		return err
-		//logger.Error(err, "could not make a connection between the gateway switch and the NED. Internal SDN controller error.")
+		return nettypes.NetworkAttachmentDefinition{}, fmt.Errorf("could not make a connection between the internal switch and the NED. Internal SDN controller error: %s", err)
+
 	}
 
 	netAttachDef.Labels[netAttachDefLabel] = "true"
 	err = r.Client.Update(ctx, netAttachDef)
 	if err != nil {
-		return err
-		//.Error(err, "Could not update network attachment definition")
+		return nettypes.NetworkAttachmentDefinition{}, fmt.Errorf("could not update network attachment definition: %s", err)
 
 	}
 
-	return nil
+	return *netAttachDef, nil
 }
diff --git a/src/kubernetes-api/internal/nedinterface/nedinterface.go b/src/kubernetes-api/internal/nedinterface/nedinterface.go
index be1ba58898f8bd57744d83b9f1976db234acef11..6c5708660c9f2f9150738bf2fa3b4f200925ad02 100644
--- a/src/kubernetes-api/internal/nedinterface/nedinterface.go
+++ b/src/kubernetes-api/internal/nedinterface/nedinterface.go
@@ -1,5 +1,53 @@
 package nedinterface
 
-func GetConnectionInfo() (string, string) {
-	return "", ""
+import (
+	"context"
+	"fmt"
+	"os"
+	"time"
+
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+
+	nedpb "l2sm.local/ovs-switch/pkg/nedpb"
+)
+
+// GetConnectionInfo communicates with the NED via gRPC and returns the InterfaceNum and NodeName.
+func AttachInterface(nedNetworkAttachDef string) (string, error) {
+	// Get the NED address (e.g., from environment variable or configuration)
+	nedAddress := os.Getenv("NED_ADDRESS")
+	if nedAddress == "" {
+		nedAddress = "localhost:50051" // default address
+	}
+
+	// Set up a connection to the server.
+	client, err := grpc.NewClient(nedAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		return "", fmt.Errorf("did not connect: %v", err)
+	}
+
+	defer client.Close()
+
+	c := nedpb.NewNedServiceClient(client)
+
+	// Set a timeout for the context
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
+	defer cancel()
+
+	// Now call AttachInterface
+	attachReq := &nedpb.AttachInterfaceRequest{
+		InterfaceName: nedNetworkAttachDef,
+	}
+
+	attachRes, err := c.AttachInterface(ctx, attachReq)
+	if err != nil {
+		return "", fmt.Errorf("could not attach interface: %v", err)
+	}
+
+	return fmt.Sprint(attachRes.GetInterfaceNum()), nil
+}
+
+// TODO
+func GetNodeName(providerName string) string {
+	return ""
 }