From 8e1418043620f6a4d36ff670e439d49c66345129 Mon Sep 17 00:00:00 2001 From: cbaugus Date: Fri, 5 Sep 2025 10:04:56 -0500 Subject: [PATCH] Add GCP (Google Cloud Platform) mode support Implements GCP subnet mode which reserves 4 addresses per subnet according to Google Cloud VPC documentation: - Network address (first address) - Default gateway (second address) - Reserved for future use (second-to-last address) - Broadcast address (last address) Changes: - Added GCP mode to the Tools dropdown menu - Configured minimum subnet size as /29 for GCP - Updated address calculation logic to reserve correct addresses - Added appropriate validation and error messages - Updated documentation in README.md - Included links to official GCP documentation This aligns with GCP's subnet requirements as documented at: https://cloud.google.com/vpc/docs/subnets#unusable-ip-addresses-in-every-subnet --- README.md | 9 +++++++++ dist/index.html | 1 + dist/js/main.js | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7ffc816..6f684ef 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,15 @@ should align to these tenets, or propose an adjustment to the tenets. - Azure Reserved - DNS Mapping - Broadcast Address (last network address) +### GCP mode ([docs](https://cloud.google.com/vpc/docs/subnets#unusable-ip-addresses-in-every-subnet)): + +- Smallest subnet: /29 +- Four reserved addresses per subnet: + - Network Address (network + 0) + - GCP Reserved - Default Gateway (network + 1) + - GCP Reserved - Future Use (second-to-last address) + - Broadcast Address (last network address) + ### OCI mode ([docs](https://docs.oracle.com/en-us/iaas/Content/Network/Concepts/overview.htm#Reserved__reserved_subnet)): - Smallest subnet: /30 diff --git a/dist/index.html b/dist/index.html index 401293e..fdde4a0 100644 --- a/dist/index.html +++ b/dist/index.html @@ -107,6 +107,7 @@

Visual Subnet Calculator

  • Mode - Standard
  • Mode - AWS
  • Mode - Azure
  • +
  • Mode - GCP
  • Mode - OCI
  • Import / Export
  • diff --git a/dist/js/main.js b/dist/js/main.js index d4b96a5..f913963 100644 --- a/dist/js/main.js +++ b/dist/js/main.js @@ -29,6 +29,13 @@ let infoColumnCount = 5 // - Net+0 = Network Address // - Net+1 = OCI Reserved - Default Gateway Address // - Last = Broadcast Address +// GCP mode: +// - Smallest subnet: /29 +// - Four reserved addresses per subnet: +// - Net+0 = Network Address +// - Net+1 = GCP Reserved - Default Gateway +// - Net+Last-1 = GCP Reserved - Future Use +// - Last = Broadcast Address let noteTimeout; let operatingMode = 'Standard' let previousOperatingMode = 'Standard' @@ -40,6 +47,7 @@ const netsizePatterns = { Standard: '^([12]?[0-9]|3[0-2])$', AZURE: '^([12]?[0-9])$', AWS: '^(1?[0-9]|2[0-8])$', + GCP: '^([12]?[0-9])$', OCI: '^([12]?[0-9]|30)$', }; @@ -47,6 +55,7 @@ const minSubnetSizes = { Standard: 32, AZURE: 29, AWS: 28, + GCP: 29, OCI: 30, }; @@ -131,6 +140,16 @@ $('#dropdown_aws').click(function() { } }); +$('#dropdown_gcp').click(function() { + previousOperatingMode = operatingMode; + operatingMode = 'GCP'; + + if(!switchMode(operatingMode)) { + operatingMode = previousOperatingMode; + $('#dropdown_'+ operatingMode.toLowerCase()).addClass('active'); + } +}); + $('#dropdown_oci').click(function() { previousOperatingMode = operatingMode; operatingMode = 'OCI'; @@ -279,7 +298,7 @@ function addRow(network, netSize, colspan, note, notesWidth, color, operatingMod let addressFirst = ip2int(network) let addressLast = subnet_last_address(addressFirst, netSize) let usableFirst = subnet_usable_first(addressFirst, netSize, operatingMode) - let usableLast = subnet_usable_last(addressFirst, netSize) + let usableLast = subnet_usable_last(addressFirst, netSize, operatingMode) let hostCount = 1 + usableLast - usableFirst let styleTag = '' if (color !== '') { @@ -432,14 +451,17 @@ function subnet_usable_first(network, netSize, operatingMode) { // AWS reserves 3 additional IPs // https://learn.microsoft.com/en-us/azure/virtual-network/virtual-networks-faq#are-there-any-restrictions-on-using-ip-addresses-within-these-subnets // Azure reserves 3 additional IPs + // https://cloud.google.com/vpc/docs/subnets + // GCP reserves 2 additional IPs at the start // https://docs.oracle.com/en-us/iaas/Content/Network/Concepts/overview.htm#Reserved__reserved_subnet - // OCI reserves 2 additional IPs + // OCI reserves 1 additional IP //return network + (operatingMode == 'Standard' ? 1 : 4); switch (operatingMode) { case 'AWS': case 'AZURE': return network + 4; break; + case 'GCP': case 'OCI': return network + 2; break; @@ -452,10 +474,15 @@ function subnet_usable_first(network, netSize, operatingMode) { } } -function subnet_usable_last(network, netSize) { +function subnet_usable_last(network, netSize, operatingMode) { let last_address = subnet_last_address(network, netSize); if (netSize < 31) { - return last_address - 1; + // GCP reserves the last 2 addresses (second-to-last and broadcast) + if (operatingMode === 'GCP') { + return last_address - 2; + } else { + return last_address - 1; + } } else { return last_address; } @@ -618,6 +645,9 @@ function mutate_subnet_map(verb, network, subnetTree, propValue = '') { case 'AZURE': var modal_error_message = 'The minimum IPv4 subnet size for Azure is /' + minSubnetSizes[operatingMode] + '.

    More Information:
    Azure Virtual Network FAQ > How small and how large can virtual networks and subnets be?' break; + case 'GCP': + var modal_error_message = 'The minimum IPv4 subnet size for GCP is /' + minSubnetSizes[operatingMode] + '.

    More Information:
    Google Cloud VPC > Subnets > Unusable addresses in IPv4 subnet ranges' + break; case 'OCI': var modal_error_message = 'The minimum IPv4 subnet size for OCI is /' + minSubnetSizes[operatingMode] + '.

    More Information:
    Infrastructure Services>Networking>Networking Overview>Three IP Addresses in Each Subnet' break; @@ -669,6 +699,9 @@ function switchMode(operatingMode) { case 'AZURE': var validate_error_message = 'Azure Mode - Smallest size is /' + minSubnetSizes[operatingMode] break; + case 'GCP': + var validate_error_message = 'GCP Mode - Smallest size is /' + minSubnetSizes[operatingMode] + break; case 'OCI': var validate_error_message = 'OCI Mode - Smallest size is /' + minSubnetSizes[operatingMode] break; @@ -688,7 +721,7 @@ function switchMode(operatingMode) { } }); // Remove active class from all buttons if needed - $('#dropdown_standard, #dropdown_azure, #dropdown_aws, #dropdown_oci').removeClass('active'); + $('#dropdown_standard, #dropdown_azure, #dropdown_aws, #dropdown_gcp, #dropdown_oci').removeClass('active'); $('#dropdown_' + operatingMode.toLowerCase()).addClass('active'); isSwitched = true; } else { @@ -699,6 +732,9 @@ function switchMode(operatingMode) { case 'AZURE': var modal_error_message = 'One or more subnets are smaller than the minimum allowed for Azure.
    The smallest size allowed is /' + minSubnetSizes[operatingMode] + '.
    See: Azure Virtual Network FAQ > How small and how large can virtual networks and subnets be?' break; + case 'GCP': + var modal_error_message = 'One or more subnets are smaller than the minimum allowed for GCP.
    The smallest size allowed is /' + minSubnetSizes[operatingMode] + '.
    See: Google Cloud VPC > Subnets > Unusable addresses in IPv4 subnet ranges' + break; case 'OCI': var modal_error_message = 'One or more subnets are smaller than the minimum allowed for OCI.
    The smallest size allowed is /' + minSubnetSizes[operatingMode] + '.
    See: Infrastructure Services>Networking>Networking Overview>Three IP Addresses in Each Subnet' break; @@ -747,6 +783,9 @@ function set_usable_ips_title(operatingMode) { case 'AZURE': $('#useableHeader').html('Usable IPs (Azure)') break; + case 'GCP': + $('#useableHeader').html('Usable IPs (GCP)') + break; case 'OCI': $('#useableHeader').html('Usable IPs (OCI)') break;