summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbatleram <batleram@gmail.com>2026-10-24 15:13:04 -0400
committerbatleram <batleram@gmail.com>2026-10-24 15:25:09 -0400
commita38f91aff987f01cc885771554b4cd142599df3f (patch)
treec1d8caf1e5c9a1364c1c8bdf08345c58dfe203c3
initial baseline ~2500ms
-rw-r--r--.gitignore2
-rw-r--r--Makefile13
-rw-r--r--calc.c104
-rw-r--r--calc.h15
4 files changed, 134 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d629681
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.json
+calc
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..75b6c76
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+
+.PHONY: build
+
+build: calc.c
+ clang -o calc -O3 -ggdb ./calc.c
+
+bench: build
+ ./calc 10.0.0.0/8 2
+
+bench2: build
+ ./calc 10.0.0.0/6 2
+
+
diff --git a/calc.c b/calc.c
new file mode 100644
index 0000000..2f533b1
--- /dev/null
+++ b/calc.c
@@ -0,0 +1,104 @@
+#include "calc.h"
+#include <time.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+
+int print_usage() {
+ printf("Invalid arguments:\n\tcalc <network/cidr> <ips per subnet>\n");
+
+ return 1;
+}
+
+uint32_t calc_netmask(unsigned int cidr) {
+ return UINT32_MAX << (32 - cidr);
+}
+
+uint32_t segments_to_ip(unsigned int segments[4]) {
+ return (segments[0] << 3*8) | (segments[1] << 2*8) | (segments[2] << 1*8) | (segments[3]);
+}
+
+uint32_t subnetmask_for_netspace(unsigned int desired_netspace) {
+ uint32_t start = UINT32_MAX;
+ // +1 because 2s complement
+ while (~start +1 < desired_netspace + 2) {
+ start = start << 1;
+ }
+ return start;
+}
+
+
+int main(int argc, char** argv) {
+ struct timespec start;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ unsigned int segments[4] = {0};
+ unsigned int cidr = 0;
+ unsigned int min_ips_per_subnet = 0;
+ // parse args
+ if (argc < 3) {
+ return print_usage();
+ }
+ if (sscanf(argv[1], "%u.%u.%u.%u/%u", &segments[0], &segments[1], &segments[2], &segments[3], &cidr) != 5) return print_usage();
+ if (sscanf(argv[2], "%u", &min_ips_per_subnet) != 1) return print_usage();
+
+ CalcRequest req = {
+ .network = segments_to_ip(segments), // fixed later
+ .netmask = calc_netmask(cidr),
+ .subnet_mask = subnetmask_for_netspace(min_ips_per_subnet),
+ .count = 0, // later
+ };
+ // User can provide any ip address, this converts it to the network address
+ req.network = req.network & req.netmask;
+ // +1 because 2s complement
+ const unsigned int ips_per_subnet = ~req.subnet_mask + 1;
+ req.count = (~req.netmask+1) / (ips_per_subnet);
+
+ FILE *out = fopen("file.json", "w");
+ if (out == NULL) {
+ perror("Failed to open output file:");
+ return errno;
+ }
+
+
+ fprintf(out, "[\n"); // file start
+ uint32_t offset = 0;
+ int i = 0;
+ while (i<req.count) {
+ const uint32_t network = req.network + offset;
+ const uint32_t first = network + 1;
+ const uint32_t broadcast = first + ips_per_subnet - 2;
+ const uint32_t last = broadcast - 1;
+ offset += ips_per_subnet;
+ if (i+1 == req.count) {
+ fprintf(out,
+ "\t{\n\t\t\"Reseau\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Premiere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Derniere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Broadcast\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Nbr\": \"%hu\"\n\t}\n",
+ UINT_TO_SEGMENTS(network),
+ UINT_TO_SEGMENTS(first),
+ UINT_TO_SEGMENTS(last),
+ UINT_TO_SEGMENTS(broadcast),
+ ips_per_subnet - 2
+ );
+ break;
+ }
+ fprintf(out,
+ "\t{\n\t\t\"Reseau\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Premiere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Derniere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Broadcast\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Nbr\": \"%hu\"\n\t},\n",
+ UINT_TO_SEGMENTS(network),
+ UINT_TO_SEGMENTS(first),
+ UINT_TO_SEGMENTS(last),
+ UINT_TO_SEGMENTS(broadcast),
+ ips_per_subnet - 2
+ );
+ i++;
+ }
+ fprintf(out, "]"); // file end
+ fflush(out);
+ fclose(out);
+
+ struct timespec end;
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ printf("Time elapsed: %llu ms\n", (unsigned long long)((end.tv_sec - start.tv_sec) * 1e3 + (end.tv_nsec - start.tv_nsec) / 1e6));
+
+ return 0;
+}
diff --git a/calc.h b/calc.h
new file mode 100644
index 0000000..ea01529
--- /dev/null
+++ b/calc.h
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+#define UINT_TO_SEGMENTS(i) (i>>24 & 0xff),(i>>16 & 0xff),(i>>8 & 0xff),(i & 0xff)
+
+int print_usage();
+uint32_t calc_netmask(unsigned int cidr);
+uint32_t segments_to_ip(unsigned int segments[4]);
+uint32_t cidr_for_netspace(unsigned int desired_netspace);
+
+typedef struct {
+ uint32_t network;
+ uint32_t netmask;
+ uint32_t subnet_mask;
+ uint32_t count;
+} CalcRequest;