extnetip

package module
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2025 License: MIT Imports: 4 Imported by: 8

README

Go Reference GitHub release (latest SemVer) CI Go Report Card Coverage Status Stand With Ukraine

package extnetip

Package extnetip is an extension to the Go standard library package net/netip, providing a set of important auxiliary functions currently missing from netip for converting IP prefixes to IP ranges and vice versa.

With these extensions, it becomes straightforward to build third-party IP-range libraries based on net/netip.

API

import "github.com/gaissmai/extnetip"

func Range(p netip.Prefix) (first, last netip.Addr)
func Prefix(first, last netip.Addr) (prefix netip.Prefix, ok bool)
func CommonPrefix(pfx1, pfx2 netip.Prefix) (pfx netip.Prefix)
func All(first, last netip.Addr) iter.Seq[netip.Prefix]

Unsafe Mode

This package supports two modes of operation for converting between netip.Addr and a custom internal uint128 representation:

  • When built with the unsafe build tag (e.g., go build -tags=unsafe), conversions use unsafe.Pointer to perform zero-copy, direct memory reinterpretation. This method is significantly faster.

  • Without the unsafe build tag, conversions are performed safely by using binary.ByteOrder-based byte slice manipulations, avoiding use of the unsafe package. This is the default mode and is suitable when importing unsafe modules is prohibited.

Performance Benchmark

Below is a benchmark comparing the safe (default) and unsafe conversion methods:

goos: linux
goarch: amd64
pkg: github.com/gaissmai/extnetip
cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
                  │   safe.bm    │             unsafe.bm              │
                  │    sec/op    │   sec/op     vs base               │
Range/v4-8          12.435n ± 0%   5.099n ± 1%  -58.99% (p=0.002 n=6)
Range/v6-8          25.855n ± 0%   5.399n ± 0%  -79.12% (p=0.002 n=6)
Prefix/v4-8          16.31n ± 0%   12.07n ± 1%  -25.99% (p=0.002 n=6)
Prefix/v6-8          17.38n ± 1%   10.88n ± 1%  -37.45% (p=0.002 n=6)
CommonPrefix/v4-8    26.79n ± 0%   21.58n ± 1%  -19.43% (p=0.002 n=6)
CommonPrefix/v6-8    28.25n ± 0%   21.00n ± 1%  -25.63% (p=0.002 n=6)
geomean              20.25n        10.86n       -46.38%

Future Work

It is hoped that these frequently needed helper functions will be added to the Go standard library's netip package at some point in the future by the maintainers.

Until then, extnetip provides a robust and efficient alternative.

Documentation

Overview

Package extnetip is an extension to net/netip providing auxiliary functions for converting IP prefixes to IP ranges and vice versa.

The calculations are done efficiently in uint128 space, avoiding conversions to/from byte slices. These extensions allow easy implementation of third-party libraries for IP range management on top of net/netip.

This package supports both safe and unsafe modes of operation. When built with the 'unsafe' build tag, conversions use unsafe.Pointer for better performance. Without the tag, safe byte-slice based conversions are used.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func All added in v1.1.0

func All(first, last netip.Addr) iter.Seq[netip.Prefix]

All returns an iterator over all netip.Prefix values that cover the entire inclusive IP range [first, last].

If either IP is invalid, the order is wrong, or versions differ, the iterator yields no results.

This uses a recursive subdivision approach to partition the range into a minimal set of CIDRs.

Example
package main

import (
	"fmt"
	"net/netip"

	"github.com/gaissmai/extnetip"
)

func main() {
	first := netip.MustParseAddr("10.1.0.0")
	last := netip.MustParseAddr("10.1.13.233")

	fmt.Println("Prefixes:")
	for pfx := range extnetip.All(first, last) {
		fmt.Println(pfx)
	}

}
Output:

Prefixes:
10.1.0.0/21
10.1.8.0/22
10.1.12.0/24
10.1.13.0/25
10.1.13.128/26
10.1.13.192/27
10.1.13.224/29
10.1.13.232/31

func CommonPrefix added in v1.3.0

func CommonPrefix(pfx1, pfx2 netip.Prefix) (pfx netip.Prefix)

CommonPrefix returns the longest prefix shared by pfx1 and pfx2. It returns the zero value if a prefix is invalid or if the IP versions do not match. Otherwise it compares both addresses and returns the prefix covering their common range.

func Prefix

func Prefix(first, last netip.Addr) (prefix netip.Prefix, ok bool)

Prefix tries to determine if the inclusive range [first, last] can be exactly represented as a single netip.Prefix. It returns the prefix and ok=true if so.

Returns ok=false for ranges that don't align exactly to a prefix, invalid IPs, mismatched versions or first > last.

The calculation is done by analyzing the uint128 values and checking prefix match conditions.

Example
package main

import (
	"fmt"
	"net/netip"

	"github.com/gaissmai/extnetip"
)

func main() {
	first := netip.MustParseAddr("fe80::")
	last := netip.MustParseAddr("fe80::7")

	pfx, ok := extnetip.Prefix(first, last)

	fmt.Println("OK:    ", ok)
	fmt.Println("Prefix:", pfx)

	fmt.Println()

	first = netip.MustParseAddr("10.0.0.1")
	last = netip.MustParseAddr("10.0.0.19")

	pfx, ok = extnetip.Prefix(first, last)

	fmt.Println("OK:    ", ok)
	fmt.Println("Prefix:", pfx)

}
Output:

OK:     true
Prefix: fe80::/125

OK:     false
Prefix: invalid Prefix

func Prefixes deprecated

func Prefixes(first, last netip.Addr) []netip.Prefix

Deprecated: Prefixes is deprecated. Use the iterator version All instead.

func PrefixesAppend deprecated added in v0.3.0

func PrefixesAppend(dst []netip.Prefix, first, last netip.Addr) []netip.Prefix

Deprecated: PrefixesAppend is deprecated. Use the iterator version All instead.

func Range

func Range(p netip.Prefix) (first, last netip.Addr)

Range returns the inclusive IP address range [first, last] covered by the given prefix p.

The prefix p does not have to be canonical.

If p is invalid, Range returns zero values.

The range calculation is performed by masking the uint128 representation according to the prefix bits.

Example
package main

import (
	"fmt"
	"net/netip"

	"github.com/gaissmai/extnetip"
)

func main() {
	pfx := netip.MustParsePrefix("fe80::/10")
	first, last := extnetip.Range(pfx)

	fmt.Println("First:", first)
	fmt.Println("Last: ", last)
}
Output:

First: fe80::
Last:  febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL