Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
5baff25
Direct Routed (L3) guest networks: route public IPv4/IPv6 directly to…
wido Jul 30, 2026
a836ad2
Direct Routed networks: ROUTED isolation method and routed://<id> bro…
wido Sep 4, 2026
befa270
Direct Routed networks: audit fixes after the isolation-model overhaul
wido Sep 4, 2026
24c0726
test: update CreateNetworkCmdTest for the L3-aware physical network I…
wido Sep 4, 2026
1f56101
Direct Routed networks: DefaultL3NetworkOffering and ROUTED in the re…
wido Sep 5, 2026
de37f40
Direct Routed networks: skip the PVLAN overlap check for routed:// URIs
wido Sep 5, 2026
a19d872
Direct Routed networks: let the UI pass an operator-chosen routed id
wido Sep 5, 2026
4a06f45
Direct Routed networks: exempt auto-allocated routed ids from the vne…
wido Sep 5, 2026
9273422
Direct Routed networks: set the public NIC's MAC before deriving its …
wido Sep 6, 2026
3b98041
Direct Routed networks: recognise a routed NIC by its broadcast URI too
wido Sep 7, 2026
655530c
Direct Routed networks: move inline comments into Javadoc
wido Sep 7, 2026
7441659
Direct Routed networks: let VM deploys with security groups target L3…
wido Sep 7, 2026
6071586
Direct Routed networks: emit a gateway key so cloud-init marks the de…
wido Sep 8, 2026
671de63
Direct Routed networks: give brdr bridges a deterministic MAC per rou…
wido Sep 8, 2026
29d3ec8
Direct Routed networks: unplug NICs when a VM start or migration prep…
wido Sep 8, 2026
4546822
Direct Routed networks: IPv4 is optional, enabling IPv6-only networks
wido Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion api/src/main/java/com/cloud/network/Network.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
public interface Network extends ControlledEntity, StateObject<Network.State>, InternalIdentity, Identity, Serializable, Displayable {

enum GuestType {
Shared, Isolated, L2;
Shared, Isolated, L2, L3;

public static GuestType fromValue(String type) {
if (StringUtils.isBlank(type)) {
Expand All @@ -54,6 +54,8 @@ public static GuestType fromValue(String type) {
return Isolated;
} else if (type.equalsIgnoreCase("L2")) {
return L2;
} else if (type.equalsIgnoreCase("L3")) {
return L3;
} else {
throw new InvalidParameterValueException("Unexpected Guest type : " + type);
}
Expand Down
17 changes: 17 additions & 0 deletions api/src/main/java/com/cloud/network/Networks.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ public <T> URI toUri(T value) {
}
}
},
/**
* Direct Routed (L3) networks: the id is a label naming the per-network bridge on the
* hypervisor (brdr-&lt;id&gt;), not an encapsulation — nothing appears on the wire.
*/
Routed("routed", Long.class) {
@Override
public <T> URI toUri(T value) {
try {
if (value.toString().contains("://"))
return new URI(value.toString());
else
return new URI("routed://" + value.toString());
} catch (URISyntaxException e) {
throw new CloudRuntimeException("Unable to convert to broadcast URI: " + value);
}
}
},
UnDecided(null, null),
OpenDaylight("opendaylight", String.class),
TUNGSTEN("tf", String.class),
Expand Down
1 change: 1 addition & 0 deletions api/src/main/java/com/cloud/offering/NetworkOffering.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ enum RoutingMode {
public final static String DefaultL2NetworkOfferingVlan = "DefaultL2NetworkOfferingVlan";
public final static String DefaultL2NetworkOfferingConfigDrive = "DefaultL2NetworkOfferingConfigDrive";
public final static String DefaultL2NetworkOfferingConfigDriveVlan = "DefaultL2NetworkOfferingConfigDriveVlan";
public final static String DefaultL3NetworkOffering = "DefaultL3NetworkOffering";

/**
* @return name for the network offering.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,10 @@ public Long getPhysicalNetworkId() {
}
}
if (physicalNetworkId != null) {
if ((offering.getGuestType() == GuestType.Shared) || (offering.getGuestType() == GuestType.L2)) {
if ((offering.getGuestType() == GuestType.Shared) || (offering.getGuestType() == GuestType.L2) || (offering.getGuestType() == GuestType.L3)) {
return physicalNetworkId;
} else {
throw new InvalidParameterValueException("Physical network ID can be specified for networks of guest IP type " + GuestType.Shared + " or " + GuestType.L2 + " only.");
throw new InvalidParameterValueException(String.format("Physical network ID can be specified for networks of guest IP type %s, %s or %s only.", GuestType.Shared, GuestType.L2, GuestType.L3));
}
} else {
if (zoneId == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ public NetworkType getNetworkType() {
}


/**
* A Direct Routed (L3) network needs the agent told when a secondary IP goes away, so the
* host route and neighbour entry are removed - otherwise the host keeps routing an address
* the Instance no longer owns, and the routing daemon keeps advertising it.
*/
private boolean isDirectRoutedNetwork() {
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
return ntwk != null && Network.GuestType.L3.equals(ntwk.getGuestType());
}

private boolean isZoneSGEnabled() {
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId());
Expand All @@ -144,7 +154,7 @@ public void execute() throws InvalidParameterValueException {
secIp = nicSecIp.getIp6Address();
}

if (isZoneSGEnabled()) {
if (isZoneSGEnabled() || isDirectRoutedNetwork()) {
//remove the security group rules for this secondary ip
boolean success = false;
success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), secIp, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public void testGetPhysicalNetworkIdForNonSharedNet() {
try {
cmd.getPhysicalNetworkId();
} catch (Exception e) {
Assert.assertTrue(e.getMessage().startsWith("Physical network ID can be specified for networks of guest IP type Shared or L2 only."));
Assert.assertTrue(e.getMessage().startsWith("Physical network ID can be specified for networks of guest IP type Shared, L2 or L3 only."));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,28 @@ public class NetworkRulesVmSecondaryIpCommand extends Command {
private String vmSecIp;
private String vmMac;
private String action;
private boolean directRouted;
private boolean applySecurityGroupRules = true;

public NetworkRulesVmSecondaryIpCommand(String vmName, VirtualMachine.Type type) {
this.vmName = vmName;
this.type = type;
}

public NetworkRulesVmSecondaryIpCommand(String vmName, String vmMac, String secondaryIp, boolean action, boolean directRouted, boolean applySecurityGroupRules) {
this(vmName, vmMac, secondaryIp, action);
this.directRouted = directRouted;
this.applySecurityGroupRules = applySecurityGroupRules;
}

public boolean isDirectRouted() {
return directRouted;
}

public boolean isApplySecurityGroupRules() {
return applySecurityGroupRules;
}

public NetworkRulesVmSecondaryIpCommand(String vmName, String vmMac, String secondaryIp, boolean action) {
this.vmName = vmName;
this.vmMac = vmMac;
Expand Down
Loading
Loading