# Layer 2 Networking

{% hint style="info" %}
Layer 2 Network is a beta feature in the 2026.1 release. Please contact the support team for further details.
{% endhint %}

A Layer 2 Network (L2 Network) is an L2-only physical network that provides basic Layer 2 connectivity between virtual machines, without managed IP addressing, routing, or security services. Layer 2 Networks are available only when creating Physical Networks. Virtual Networks are always Managed Networks and do not have an L2 option.

Use a Layer 2 Network when your infrastructure already handles IP management externally, or when you are migrating workloads from VMware and want equivalent L2 behaviour without adopting managed networking. If you need subnets, DHCP, routers, or security groups, use a managed [Virtual Network](/private-cloud-director/virtualized-networking/networks-and-ports.md) or [Physical Network](/private-cloud-director/virtualized-networking/physical-network.md) instead.

### How Layer 2 Networks Work

Layer 2 Networks provide pure Layer 2 connectivity between VMs. This means:

* **No managed IP addressing.** You configure IP addresses directly inside the guest OS using static assignment or an external DHCP server.
* **No routing.** VMs on the same Layer 2 Network communicate at Layer 2. Cross-network traffic requires external routing infrastructure.
* **No security groups.** Port-level security is managed outside of <code class="expression">space.vars.product\_name</code>.
* **No subnet configuration.** Layer 2 Networks operate only at the data link layerCreate a Layer 2 Network

### **Prerequisites**

* A physical network must be configured in your cluster blueprint. See [Cluster Blueprint](/private-cloud-director/virtualized-clusters/virtualized-cluster-blueprint.md)
* The VLAN ID you specify must exist on your physical network infrastructure.

Perform the following steps.

1. On the <code class="expression">space.vars.product\_name</code> UI , navigate to **Networks and Security > Networks**.
2. Select **Create Network** and then select **Physical Network**.
3. Under **Basic Information**, enter the following details.

<table><thead><tr><th width="196.56640625">Field</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Enter a name for the network.</td></tr><tr><td>Description</td><td>Optionally, enter a description.</td></tr><tr><td>Admin State</td><td>Select <strong>Up</strong> to make the network available for VM provisioning immediately, or <strong>Down</strong> to defer availability.</td></tr><tr><td>MTU</td><td>Optionally, set the maximum transmission unit. Minimum value is <code>68</code> for IPv4 and <code>1280</code> for IPv6.</td></tr></tbody></table>

4. Under **Network Type**, select **Layer 2 Network**.

{% hint style="info" %}
**NOTE**\
Selecting **Layer 2 Network** hides all subnets, DHCP, router, security groups, and public IP fields. These are not applicable to Layer 2 Networks. If you choose to configure these instances, configure the **Network Type** to **Managed Network**.
{% endhint %}

5. Enter the following details.

<table><thead><tr><th width="226.96484375">Field</th><th>Description</th></tr></thead><tbody><tr><td>Network Label</td><td>Select the network label that maps this network to the corresponding physical network on your hypervisors.</td></tr><tr><td>Network Type</td><td>Select <strong>Flat (Untagged)</strong> for a network with no VLAN tags, or <strong>VLAN (Tagged)</strong> for a network that uses VLAN tagging.</td></tr></tbody></table>

6. Optionally, select **Make Shared (Across All Tenants)** to make the network type available to every tenant.
7. Select **Create Physical Network**.

The network appears in **Networks and Security > Networks** with a **Layer 2 Network** tag corresponding to the network name.

#### **Using pcdctl CLI**

```bash
pcdctl network create \
    --provider-physical-network PHYSICAL_NETWORK_LABEL  \
    --provider-network-type NETWORK_TYPE \
    --provider-segment VLAN_TAG \
    --tag simple_network \
    --disable-port-security \
    NETWORK_NAME
```

<table><thead><tr><th width="275.3828125">Parameter</th><th>Description</th></tr></thead><tbody><tr><td><code>PHYSICAL_NETWORK_LABEL</code></td><td>The label configured in the blueprint.</td></tr><tr><td><code>NETWORK_TYPE</code></td><td>Either <code>vlan</code> or <code>flat</code>.</td></tr><tr><td><code>VLAN_TAG</code></td><td>The VLAN tag. Only required if <code>NETWORK_TYPE</code> is <code>vlan</code>.</td></tr><tr><td><code>NETWORK_NAME</code></td><td>The name you want to assign to the network.</td></tr></tbody></table>

The `--disable-port-security` option is required for L2-only networks because port security is a Layer 3 feature and does not apply to L2-only networks.

On a successful network creation, you should see a similar output.

<pre class="language-bash"><code class="lang-bash"><strong>$ pcdctl network create \
</strong>    --provider-network-type vlan \
    --provider-segment 1234 \
    --provider-physical-network physnet \
    --tag simple_network \
    --disable-port-security \
    my-net
<strong>+---------------------------+--------------------------------------+
</strong>| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2026-03-05T18:58:02Z                 |
| description               |                                      |
| dns_domain                |                                      |
| id                        | c2d9b7a4-88e0-480b-99a3-576ce202adf2 |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | False                                |
| is_vlan_qinq              | None                                 |
| is_vlan_transparent       | None                                 |
| mtu                       | 9000                                 |
| name                      | my-net                         |
| port_security_enabled     | false                                 |
| project_id                | 635d175b6dec4b44899acd475a837cfc     |
| provider:network_type     | vlan                                 |
| provider:physical_network | physnet                              |
| provider:segmentation_id  | 1234                                 |
| qos_policy_id             | None                                 |
| revision_number           | 1                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      | simple_network                              |
| tenant_id                 | 034e5250cf6f48baaf59ffba6bea08b3     |
| updated_at                | 2026-03-05T18:58:02Z                 |
+---------------------------+--------------------------------------+
</code></pre>

### Deploy a VM on a Layer 2 Network

You can configure a VM for a Layer 2 Network when deploying a new VM from the Virtual Machines section.

1. Navigate to **Virtual Machines > Virtual Machines**.
2. Select **Deploy New VM** and proceed through the VM creation wizard.
3. On **Select Network Type**, choose **Layer 2 Network**.
4. Select the Layer 2 Network you want to use from the list.\
   Managed Network options show IP configuration fields. Layer 2 Network selection hides all IP configuration fields.
5. Select **Next Step** to continue creating the VM.

{% hint style="info" %}
**NOTE**

When deploying a VM on a Layer 2 Network:

* The security group field is disabled and cannot be changed.
* You can only create one VM at a time. To create multiple VMs on the same Layer 2 Network, repeat the deployment process for each VM.
  {% endhint %}

6. Complete the remaining VM configuration and select **Deploy**.

After deployment, the VM instance details the following for the network attachment:

* **Network**: `[Network Name] (Layer 2)`
* **IP Address**: `N/A — Configure in guest OS`

{% hint style="info" %}
**NOTE**

* **External DHCP configuration:** If using an external DHCP server for IP assignment, ensure the DHCP server is reachable in the L2 network's broadcast domain.
* **Cloud-init workaround for network configuration**: There is a known issue with [setting network configurations in cloud-init](https://docs.cloud-init.io/en/latest/reference/network-config.html). As a workaround, use the `runcmd` [section of cloud-init](https://docs.cloud-init.io/en/latest/reference/yaml_examples/boot_cmds.html) to configure static IP or DHCP.
  {% endhint %}

Here is an example for an Ubuntu VM.

{% hint style="info" %}
**NOTE**

You may need to make changes to make this work for other operating systems.
{% endhint %}

<pre class="language-yaml"><code class="lang-yaml"><strong>runcmd:
</strong>  - |
    cat &#x3C;/etc/netplan/99-static.yaml
    network:
      version: 2
      ethernets:
        ens3:
          dhcp4: false
          addresses:
            - 10.10.10.50/24
          gateway4: 10.10.10.1
          nameservers:
            addresses: [8.8.8.8, 8.8.4.4]
    EOF
  - netplan apply
</code></pre>

#### **Using pcdctl CLI**

Create the L2-only port that will be associated with the VM:

```bash
pcdctl port create \
    --network NETWORK_NAME_OR_ID \
    --disable-port-security \
    --no-fixed-ip \
    --binding-profile '{"l2-port": true}' \
    PORT_NAME
```

This command returns the port ID upon successful creation.

Here is an example of the output.

```bash
pcdctl port create \
    --network my-net \   
    --disable-port-security \
    --no-fixed-ip \
    --binding-profile l2-port=true \
    my-l2-port
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| admin_state_up          | UP                                   |
| allowed_address_pairs   |                                      |
| binding_host_id         |                                      |
| binding_profile         | l2-port='true'                       |
| binding_vif_details     |                                      |
| binding_vif_type        | unbound                              |
| binding_vnic_type       | normal                               |
| created_at              | 2026-03-05T22:11:58Z                 |
| data_plane_status       | None                                 |
| description             |                                      |
| device_id               |                                      |
| device_owner            |                                      |
| device_profile          | None                                 |
| dns_assignment          |                                      |
| dns_domain              |                                      |
| dns_name                |                                      |
| extra_dhcp_opts         |                                      |
| fixed_ips               |                                      |
| hardware_offload_type   | None                                 |
| hints                   |                                      |
| id                      | f86dd5d6-fd59-4a84-a0e9-1c2b9722a582 |
| ip_allocation           | None                                 |
| mac_address             | fa:16:3e:dd:12:a6                    |
| name                    | my-l2-port                           |
| network_id              | c2d9b7a4-88e0-480b-99a3-576ce202adf2 |
| numa_affinity_policy    | None                                 |
| port_security_enabled   | False                                |
| project_id              | 635d175b6dec4b44899acd475a837cfc     |
| propagate_uplink_status | None                                 |
| resource_request        | None                                 |
| revision_number         | 1                                    |
| qos_network_policy_id   | None                                 |
| qos_policy_id           | None                                 |
| security_group_ids      |                                      |
| status                  | DOWN                                 |
| tags                    |                                      |
| trunk_details           | None                                 |
| updated_at              | 2026-03-05T22:11:58Z                 |
+-------------------------+--------------------------------------+
```

Attach the port created and create a VM:

```bash
pcdctl server create \
    --flavor  \
    --image  \
    --nic port-id=PORT_ID_FROM_ABOVE \
    VM_NAME
```

Here is an example.

```bash
pcdctl server create \
    --flavor m1.tiny \
    --image 889fb5f1-f1cf-44d7-a12a-6fb42d4d1e60 \
    --nic port-id=f86dd5d6-fd59-4a84-a0e9-1c2b9722a582 \
    my-vm
+--------------------------------------+---------------------------------------------------------------------+
| Field                                | Value                                                               |
+--------------------------------------+---------------------------------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                                              |
| OS-EXT-AZ:availability_zone          |                                                                     |
| OS-EXT-SRV-ATTR:host                 | None                                                                |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | None                                                                |
| OS-EXT-SRV-ATTR:instance_name        |                                                                     |
| OS-EXT-STS:power_state               | NOSTATE                                                             |
| OS-EXT-STS:task_state                | scheduling                                                          |
| OS-EXT-STS:vm_state                  | building                                                            |
| OS-SRV-USG:launched_at               | None                                                                |
| OS-SRV-USG:terminated_at             | None                                                                |
| accessIPv4                           |                                                                     |
| accessIPv6                           |                                                                     |
| addresses                            |                                                                     |
| adminPass                            | dLC4vKgnNgEF                                                        |
| config_drive                         |                                                                     |
| created                              | 2026-03-05T22:22:09Z                                                |
| flavor                               | m1.tiny (6f3d4b95-fa8e-49c1-a494-4f338f72871d)                      |
| hostId                               |                                                                     |
| id                                   | 99b3addc-0fcb-44e3-a54c-14edfa915375                                |
| image                                | cirros-0.6.2-x86_64-disk.img (889fb5f1-f1cf-44d7-a12a-6fb42d4d1e60) |
| key_name                             | None                                                                |
| name                                 | my-vm                                                               |
| os-extended-volumes:volumes_attached | []                                                                  |
| progress                             | 0                                                                   |
| project_id                           | 635d175b6dec4b44899acd475a837cfc                                    |
| properties                           |                                                                     |
| security_groups                      | name='default'                                                      |
| status                               | BUILD                                                               |
| updated                              | 2026-03-05T22:22:09Z                                                |
| user_id                              | a2dc5954fe2540a8b1825beb76834e12                                    |
+--------------------------------------+---------------------------------------------------------------------+
```

### Configure a static IP with cloud-init

The `network:` block in a cloud-init `user_data` payload is not applied to VMs on a Layer 2 Network. To assign a static IP, default gateway, and DNS servers, use the `write_files` and `runcmd` cloud-init modules instead. This is a known platform behavior and cannot be changed by configuration.

Ports on a Layer 2 Network are created without a fixed IP. As a result, Nova builds the VM's Config Drive with an empty network configuration. On first boot, cloud-init reads the Config Drive as its network data source and applies that empty configuration. When cloud-init then processes your `user_data`, it treats network configuration as already handled and ignores the `network:`

Before you begin, confirm the following:

* You have a Layer 2 Network in your project. See
* You have the static IP address (in CIDR notation), default gateway, and DNS server addresses for your environment.
* Your VM image includes `cloud-init` and the network configuration tool referenced in your `write_files` target. The example in this section targets an Ubuntu image, where Netplan is the default.
* You know the primary network interface name inside the guest. On Ubuntu cloud images, this is typically `ens3`. To confirm your image, run `ip link` on a booted VM from the same image.

#### Apply the configuration

Supply the following cloud-init payload as the user data when you deploy the VM. The example uses sample values. Replace the IP address, subnet, gateway, and DNS server values with the ones for your environment.

```yaml
#cloud-config
password: <YOUR_PASSWORD>
chpasswd: { expire: False }
ssh_pwauth: True
manage_etc_hosts: true

write_files:
  - path: /etc/netplan/99-custom-static.yaml
    content: |
      network:
        version: 2
        ethernets:
          ens3:
            dhcp4: no
            addresses: [10.10.1.35/18]
            routes:
              - to: 10.10.0.0/18
                via: 10.10.0.1
                metric: 100
              - to: default
                metric: 100
                via: 10.10.0.1
            nameservers:
              addresses: [8.8.8.8, 8.8.4.4]

runcmd:
  - netplan apply
```

The `write_files` module creates `/etc/netplan/99-custom-static.yaml` on the VM during the cloud-init `final` stage. The `runcmd` module then runs `netplan apply` to load the configuration. The static IP, routes, and DNS servers persist across reboots.

{% hint style="info" %}
**NOTE**

The `password` and `ssh_pwauth` lines in this example are inherited from the underlying test payload and are not required for the static IP workaround. Avoid placing plaintext passwords in `user_data` for production VMs. Use SSH keys or your standard credential delivery mechanism instead.
{% endhint %}

#### Verify the configuration

After the VM boots, connect to it and run the following commands to confirm that cloud-init applied the configuration:

```bash
ip addr show ens3
cloud-init status --long
```

The `ip addr show` output should list the static IP you configured. The `cloud-init status` output should show `status: done`. If `cloud-init status` reports an error, inspect `/var/log/cloud-init.log` and `/var/log/cloud-init-output.log` for details.

#### Adapt the example for other operating systems

The example targets Ubuntu and Netplan. For other guest operating systems, change the `write_files` path and the `runcmd` command to match the distribution's network configuration tool. For example, on a RHEL-based image, write a NetworkManager keyfile or `ifcfg` file and reload it with `nmcli connection reload` followed by `nmcli connection up <CONNECTION_NAME>`.

### Clone a VM on a Layer 2 Network

When cloning a VM, you can select a Layer 2 Network during the clone workflow.

The network selection page that appears during cloning follows the same workflow as the VM deployment process.

1. Navigate to **Virtual Machines > Virtual Machines**.
2. Select the VM you want to clone.
3. Select **Clone**.
4. On the network selection page, choose **Layer 2 Network** as the network type.
5. Select the Layer 2 Network from the list and complete the clone process.

The same limitations apply: security groups are disabled, and only one VM can be cloned at a time.

### View Layer 2 Network details

To view details and connected VMs for a Layer 2 Network:

1. Navigate to **Networks and Security > Networks**.
2. Identify Layer 2 Networks by the **Layer 2 Network** tag displayed next to each network name. Select the specific Layer 2 Network you want to inspect.

The network details page displays the network type as **Physical**. You will not be able to view details on **Subnets**, **Router Attachments**, and **DHCP Configuration**.

### Edit a Layer 2 Network

You can update the name and description of a Layer 2 Network after it is created. The VLAN ID and physical network cannot be changed.

1. Navigate to **Networks and Security > Networks**.
2. Select the Layer 2 Network you want to edit.
3. Select **Edit**.
4. Update the **Name** or **Description** as needed.
5. Select **Save**.

### Delete a Layer 2 Network

Deleting a Layer 2 Network detaches all VMs connected to it. Ensure no active workloads depend on the network before proceeding.

1. Navigate to **Networks and Security > Networks**.
2. Select the Layer 2 Network you want to delete.
3. Select **Delete**.
4. Confirm the deletion when prompted.

### Next steps

After creating a Layer 2 Network and configuring IP addresses in your guest OS, you can continue managing your VMs:

* [Virtual Machines](/private-cloud-director/virtualized-clusters/virtualmachine.md)
* [Cluster Blueprint](/private-cloud-director/virtualized-clusters/virtualized-cluster-blueprint.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.platform9.com/private-cloud-director/virtualized-networking/layer-2-networking.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
