Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

calculate-subnets

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

calculate-subnets - npm Package Compare versions

Comparing version 1.1.0 to 2.0.0

2

dist/cjs/src/types.d.ts
export interface UniformlyDistributedSubnetsArguments {
neededBlocks: number;
neededSubnets: number;
cidr: string;
}
//# sourceMappingURL=types.d.ts.map

@@ -6,9 +6,8 @@ import { Cidr } from 'cidr-calc';

*/
export declare function uniformlyDistributedSubnets({ neededBlocks, cidr, }: UniformlyDistributedSubnetsArguments): {
cidrBlocks: Cidr[];
cidrNumber: number;
maxIpsPerBlock: number;
availableSpace: number;
export declare function uniformlyDistributedSubnets({ neededSubnets, cidr, }: UniformlyDistributedSubnetsArguments): {
subnetCidrs: Cidr[];
optimalSubnetCidrPrefixLength: number;
maxIpsPerSubnet: number;
parentCidr: Cidr;
};
//# sourceMappingURL=uniformly-distributed-subnets.d.ts.map
import { Cidr } from 'cidr-calc';
import { UniformlyDistributedSubnetsArguments } from './types.js';
export declare function validate({ neededBlocks, cidr, }: UniformlyDistributedSubnetsArguments): {
export declare function validate({ neededSubnets, cidr, }: UniformlyDistributedSubnetsArguments): {
parentCidr: Cidr;
availableSpace: number;
};
//# sourceMappingURL=validate.d.ts.map
export interface UniformlyDistributedSubnetsArguments {
neededBlocks: number;
neededSubnets: number;
cidr: string;
}
//# sourceMappingURL=types.d.ts.map

@@ -6,9 +6,8 @@ import { Cidr } from 'cidr-calc';

*/
export declare function uniformlyDistributedSubnets({ neededBlocks, cidr, }: UniformlyDistributedSubnetsArguments): {
cidrBlocks: Cidr[];
cidrNumber: number;
maxIpsPerBlock: number;
availableSpace: number;
export declare function uniformlyDistributedSubnets({ neededSubnets, cidr, }: UniformlyDistributedSubnetsArguments): {
subnetCidrs: Cidr[];
optimalSubnetCidrPrefixLength: number;
maxIpsPerSubnet: number;
parentCidr: Cidr;
};
//# sourceMappingURL=uniformly-distributed-subnets.d.ts.map
import { Cidr } from 'cidr-calc';
import { UniformlyDistributedSubnetsArguments } from './types.js';
export declare function validate({ neededBlocks, cidr, }: UniformlyDistributedSubnetsArguments): {
export declare function validate({ neededSubnets, cidr, }: UniformlyDistributedSubnetsArguments): {
parentCidr: Cidr;
availableSpace: number;
};
//# sourceMappingURL=validate.d.ts.map
import { Cidr, IpAddress } from 'cidr-calc';
import assert from 'node:assert';
function validate({ neededBlocks, cidr, }) {
function validate({ neededSubnets, cidr, }) {
let parentCidr;

@@ -13,3 +13,3 @@ let availableSpace;

parentCidr = new Cidr(IpAddress.of(ipRaw), Number(cidrNumberRaw));
availableSpace = 32 - Number(cidrNumberRaw);
availableSpace = 32 - parentCidr.prefixLen;
}

@@ -20,3 +20,3 @@ catch {

if (typeof availableSpace !== 'number' ||
Number.isNaN(neededBlocks) ||
Number.isNaN(availableSpace) ||
!Number.isInteger(availableSpace) ||

@@ -27,12 +27,13 @@ availableSpace < 0 ||

}
if (typeof neededBlocks !== 'number' ||
Number.isNaN(neededBlocks) ||
!Number.isInteger(neededBlocks) ||
neededBlocks < 1 ||
neededBlocks > 2 ** availableSpace) {
throw new TypeError(`Expected "neededBlocks" to be a positive integer between 1 and ${(2 ** availableSpace).toLocaleString()} (which is 2^(32-cidrNumber))`);
if (typeof neededSubnets !== 'number' ||
Number.isNaN(neededSubnets) ||
!Number.isInteger(neededSubnets) ||
neededSubnets < 1) {
throw new TypeError(`Expected "neededSubnets" to be a positive integer.`);
}
if (neededSubnets > 2 ** availableSpace) {
throw new TypeError(`The number of subnets needed (${neededSubnets.toLocaleString()}) exceeds the available space in the parent CIDR block (${(2 ** availableSpace).toLocaleString()})`);
}
return {
parentCidr,
availableSpace,
};

@@ -44,37 +45,36 @@ }

*/
function uniformlyDistributedSubnets({ neededBlocks, cidr, }) {
const { parentCidr, availableSpace } = validate({ neededBlocks, cidr });
function uniformlyDistributedSubnets({ neededSubnets, cidr, }) {
const { parentCidr } = validate({ neededSubnets, cidr });
/**
* Where x is the CIDR number
* y is availableSpace
* z is neededBlocks
* Where x is the optimal subnet CIDR number
* y is parentCidrNumber
* z is neededSubnets
*
* Theoretical max IPs = 2^y / z
* CIDR number IP space = 2^(32-x)
* Theoretical max IPs = 2^(32-y) / z
* Optimal CIDR number IP space = 2^(32-x)
*
* Solving for theoretical `x`:
* 2^(32-x) = 2^(32-y) / z
* x = 32 - log2(2^(32-y) / z)
*
* `2^(32-x) = 2^y / z`
* ... which simplies to x = log( (2^32-y) * z / log(2) )
* but we can only do the closest power of 2, so we need to round up `x` to get the CIDR number closest to the theoretical max.
*
* but we can only do the closest power of 2, so we need to round up `x` to get our CIDR number.
* x = ceil(32 - log2(2^(32-y) / z))
*/
const cidrNumber = Math.ceil(Math.log(2 ** (32 - availableSpace) * neededBlocks) / Math.log(2));
const maxIpsPerBlock = 2 ** (32 - cidrNumber);
// Get the actual CIDR blocks needed
const cidrBlocks = [];
const optimalSubnetCidrPrefixLength = Math.ceil(32 - Math.log2(2 ** (32 - parentCidr.prefixLen) / neededSubnets));
// Get the actual subnet CIDR blocks needed
const subnetCidrs = [];
let currentCidr;
let currentRange;
let nextStartIpAddr = parentCidr.toIpRange().startIpAddr;
for (let index = 0; index < neededBlocks; index++) {
currentCidr = new Cidr(nextStartIpAddr, cidrNumber);
for (let index = 0; index < neededSubnets; index++) {
currentCidr = new Cidr(nextStartIpAddr, optimalSubnetCidrPrefixLength);
currentRange = currentCidr.toIpRange();
cidrBlocks.push(currentCidr);
subnetCidrs.push(currentCidr);
nextStartIpAddr = currentRange.endIpAddr.next();
}
const maxIpsPerSubnet = 2 ** (32 - optimalSubnetCidrPrefixLength);
return {
cidrBlocks,
cidrNumber,
maxIpsPerBlock,
availableSpace,
subnetCidrs,
optimalSubnetCidrPrefixLength,
maxIpsPerSubnet,
parentCidr,

@@ -81,0 +81,0 @@ };

export interface UniformlyDistributedSubnetsArguments {
neededBlocks: number;
neededSubnets: number;
cidr: string;
}
//# sourceMappingURL=types.d.ts.map

@@ -6,9 +6,8 @@ import { Cidr } from 'cidr-calc';

*/
export declare function uniformlyDistributedSubnets({ neededBlocks, cidr, }: UniformlyDistributedSubnetsArguments): {
cidrBlocks: Cidr[];
cidrNumber: number;
maxIpsPerBlock: number;
availableSpace: number;
export declare function uniformlyDistributedSubnets({ neededSubnets, cidr, }: UniformlyDistributedSubnetsArguments): {
subnetCidrs: Cidr[];
optimalSubnetCidrPrefixLength: number;
maxIpsPerSubnet: number;
parentCidr: Cidr;
};
//# sourceMappingURL=uniformly-distributed-subnets.d.ts.map
import { Cidr } from 'cidr-calc';
import { UniformlyDistributedSubnetsArguments } from './types.js';
export declare function validate({ neededBlocks, cidr, }: UniformlyDistributedSubnetsArguments): {
export declare function validate({ neededSubnets, cidr, }: UniformlyDistributedSubnetsArguments): {
parentCidr: Cidr;
availableSpace: number;
};
//# sourceMappingURL=validate.d.ts.map
{
"name": "calculate-subnets",
"type": "module",
"version": "1.1.0",
"version": "2.0.0",
"description": "TODO",

@@ -25,2 +25,10 @@ "license": "UNLICENSED",

],
"scripts": {
"build": "del dist && rollup -c",
"start": "tsx bin/cli.ts",
"test": "tsx --test test/**.test.ts",
"lint": "concurrently -c auto \"pnpm:lint:*\"",
"lint:prettier": "prettier --check . --log-level warn",
"lint:types": "tsc --noEmit"
},
"devDependencies": {

@@ -49,11 +57,3 @@ "@eslint/js": "^8.57.1",

"cidr-calc": "^1.0.4"
},
"scripts": {
"build": "del dist && rollup -c",
"start": "tsx bin/cli.ts",
"test": "tsx --test test/**.test.ts",
"lint": "concurrently -c auto \"pnpm:lint:*\"",
"lint:prettier": "prettier --check . --log-level warn",
"lint:types": "tsc --noEmit"
}
}
}
# Calculate Subnet CIDRs
Calculates the optimal subnet CIDRs for a network. Uses [`cidr-calc`](https://github.com/arineng/cidr-calc) for IP ranges.
Split a CIDR into the largest possible subnet CIDRs. Uses [`cidr-calc`](https://github.com/arineng/cidr-calc) for IP ranges.

@@ -10,3 +10,3 @@ ## Usage

```console
$ npx calculate-subnets --needed-blocks=9 --cidr='10.113.0.0/16'
$ npx calculate-subnets --needed-subnets=9 --cidr='10.113.0.0/16'

@@ -17,6 +17,6 @@ Network IP range: 10.113.0.0 - 10.113.255.255

Subnets' CIDR number: /20
Subnets' optimal CIDR number: /20
Max IPs per subnet: 4,096
CIDR blocks:
Subnet CIDR blocks:
Subnet 1: 10.113.0.0/20 (IP range: 10.113.0.0 - 10.113.15.255)

@@ -42,10 +42,10 @@ Subnet 2: 10.113.16.0/20 (IP range: 10.113.16.0 - 10.113.31.255)

const { cidrBlocks } = uniformlyDistributedSubnets({
neededBlocks: 9,
const { subnetCidrs } = uniformlyDistributedSubnets({
neededSubnets: 9,
cidr: '10.113.0.0/16',
});
for (const cidrBlock of cidrBlocks) {
console.log(cidrBlock.toString());
for (const subnetCidr of subnetCidrs) {
console.log(subnetCidr.toString());
}
```
export interface UniformlyDistributedSubnetsArguments {
neededBlocks: number;
neededSubnets: number;
cidr: string;
}

@@ -9,53 +9,51 @@ import { Cidr, IpRange } from 'cidr-calc';

export function uniformlyDistributedSubnets({
neededBlocks,
neededSubnets,
cidr,
}: UniformlyDistributedSubnetsArguments): {
cidrBlocks: Cidr[];
cidrNumber: number;
maxIpsPerBlock: number;
availableSpace: number;
subnetCidrs: Cidr[];
optimalSubnetCidrPrefixLength: number;
maxIpsPerSubnet: number;
parentCidr: Cidr;
} {
const { parentCidr, availableSpace } = validate({ neededBlocks, cidr });
const { parentCidr } = validate({ neededSubnets, cidr });
/**
* Where x is the CIDR number
* y is availableSpace
* z is neededBlocks
* Where x is the optimal subnet CIDR number
* y is parentCidrNumber
* z is neededSubnets
*
* Theoretical max IPs = 2^y / z
* CIDR number IP space = 2^(32-x)
* Theoretical max IPs = 2^(32-y) / z
* Optimal CIDR number IP space = 2^(32-x)
*
* Solving for theoretical `x`:
* 2^(32-x) = 2^(32-y) / z
* x = 32 - log2(2^(32-y) / z)
*
* `2^(32-x) = 2^y / z`
* ... which simplies to x = log( (2^32-y) * z / log(2) )
* but we can only do the closest power of 2, so we need to round up `x` to get the CIDR number closest to the theoretical max.
*
* but we can only do the closest power of 2, so we need to round up `x` to get our CIDR number.
* x = ceil(32 - log2(2^(32-y) / z))
*/
const cidrNumber = Math.ceil(
Math.log(2 ** (32 - availableSpace) * neededBlocks) / Math.log(2),
const optimalSubnetCidrPrefixLength = Math.ceil(
32 - Math.log2(2 ** (32 - parentCidr.prefixLen) / neededSubnets),
);
const maxIpsPerBlock = 2 ** (32 - cidrNumber);
// Get the actual CIDR blocks needed
const cidrBlocks: Cidr[] = [];
// Get the actual subnet CIDR blocks needed
const subnetCidrs: Cidr[] = [];
let currentCidr: Cidr;
let currentRange: IpRange;
let nextStartIpAddr = parentCidr.toIpRange().startIpAddr;
for (let index = 0; index < neededBlocks; index++) {
currentCidr = new Cidr(nextStartIpAddr, cidrNumber);
for (let index = 0; index < neededSubnets; index++) {
currentCidr = new Cidr(nextStartIpAddr, optimalSubnetCidrPrefixLength);
currentRange = currentCidr.toIpRange();
cidrBlocks.push(currentCidr);
subnetCidrs.push(currentCidr);
nextStartIpAddr = currentRange.endIpAddr.next();
}
const maxIpsPerSubnet = 2 ** (32 - optimalSubnetCidrPrefixLength);
return {
cidrBlocks,
cidrNumber,
maxIpsPerBlock,
availableSpace,
subnetCidrs,
optimalSubnetCidrPrefixLength,
maxIpsPerSubnet,
parentCidr,
};
}

@@ -6,7 +6,6 @@ import assert from 'node:assert';

export function validate({
neededBlocks,
neededSubnets,
cidr,
}: UniformlyDistributedSubnetsArguments): {
parentCidr: Cidr;
availableSpace: number;
} {

@@ -23,3 +22,3 @@ let parentCidr: Cidr;

parentCidr = new Cidr(IpAddress.of(ipRaw), Number(cidrNumberRaw));
availableSpace = 32 - Number(cidrNumberRaw);
availableSpace = 32 - parentCidr.prefixLen;
} catch {

@@ -31,3 +30,3 @@ throw new TypeError(`Invalid CIDR provided: ${cidr}`);

typeof availableSpace !== 'number' ||
Number.isNaN(neededBlocks) ||
Number.isNaN(availableSpace) ||
!Number.isInteger(availableSpace) ||

@@ -43,17 +42,18 @@ availableSpace < 0 ||

if (
typeof neededBlocks !== 'number' ||
Number.isNaN(neededBlocks) ||
!Number.isInteger(neededBlocks) ||
neededBlocks < 1 ||
neededBlocks > 2 ** availableSpace
typeof neededSubnets !== 'number' ||
Number.isNaN(neededSubnets) ||
!Number.isInteger(neededSubnets) ||
neededSubnets < 1
) {
throw new TypeError(`Expected "neededSubnets" to be a positive integer.`);
}
if (neededSubnets > 2 ** availableSpace) {
throw new TypeError(
`Expected "neededBlocks" to be a positive integer between 1 and ${(2 ** availableSpace).toLocaleString()} (which is 2^(32-cidrNumber))`,
`The number of subnets needed (${neededSubnets.toLocaleString()}) exceeds the available space in the parent CIDR block (${(2 ** availableSpace).toLocaleString()})`,
);
}
return {
parentCidr,
availableSpace,
};
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc