2 Commits

Author SHA1 Message Date
brent saner
d37aa3eb6b v0.1.1
ADDED:
* The -s/--size argument to the VLSM splitter may now be a
  comma-delimited list of sizes instead of needing to specify -s/--size
  for each size.
  This change is backwards-compatible.
2025-04-04 11:53:55 -04:00
brent saner
0c8577f149 v0.1.0
ADDED:
* Explicit subnet ordering option for VLSM
2025-04-03 18:35:35 -04:00
7 changed files with 94 additions and 15 deletions

View File

@@ -88,8 +88,11 @@ type XNetArgs struct {
} }
type VLSMArgs struct { type VLSMArgs struct {
Asc bool `short:"A" long:"ascending" description:"If specified, place smaller networks (larger prefixes) at the beginning. You almost assuredly do not want to do this."` Asc bool `short:"A" long:"ascending" description:"If specified, place smaller networks (larger prefixes) at the beginning. You almost assuredly do not want to do this."`
Sizes []uint8 `short:"s" long:"size" required:"true" description:"Prefix lengths. May be specified multiple times." validate:"required"` Explicit bool `short:"O" long:"explicit-order" description:"If specified, ignore -A/--ascending and do no reordering of prefix sizes whatsoever, instead using the order given. This is EXTREMELY suboptimal and can lead to drastic addressing waste."`
// Custom type for now; see https://github.com/jessevdk/go-flags/issues/245
// Sizes []uint8 `short:"s" long:"size" required:"true" description:"Prefix lengths. May be specified multiple times." validate:"required"`
Sizes []vlsmSize `short:"s" long:"size" required:"true" description:"Prefix lengths. May be specified multiple times or as a comma-delimited list." validate:"required"`
splitArgs splitArgs
} }

View File

@@ -0,0 +1,26 @@
package main
/*
AllSizes returns a properly parsed and consolidated slice
of all specified sizes, as it takes two valid syntaxes (`-s 32 -s 32`, `-s 32,32`)
that can be mixed together.
*/
func (v *VLSMArgs) AllSizes() (sizes []uint8, err error) {
var sizeSlice []uint8
if v == nil {
return
}
if v.Sizes == nil || len(v.Sizes) == 0 {
return
}
for _, s := range v.Sizes {
if sizeSlice, err = s.Sizes(); err != nil {
return
}
sizes = append(sizes, sizeSlice...)
}
return
}

View File

@@ -0,0 +1,33 @@
package main
import (
`strconv`
`strings`
)
// Sizes returns a parsed/split slice of uint8s from a vlsmSize.
func (v *vlsmSize) Sizes() (sizes []uint8, err error) {
var s []string
var u uint64
if v == nil {
return
}
s = strings.Split(string(*v), ",")
for idx, i := range s {
s[idx] = strings.TrimSpace(i)
}
sizes = make([]uint8, len(s))
// No validation is performed since we don't have access to the addr inet family; that's up to the parsers.
for idx, i := range s {
if u, err = strconv.ParseUint(i, 10, 8); err != nil {
return
}
sizes[idx] = uint8(u)
}
return
}

View File

@@ -26,6 +26,7 @@ func main() {
var pfx *net.IPNet var pfx *net.IPNet
var resPfx *netip.Prefix var resPfx *netip.Prefix
var origPfx netip.Prefix var origPfx netip.Prefix
var vlsmSizes []uint8
var splitter netsplit.NetSplitter var splitter netsplit.NetSplitter
var cmnArgs common var cmnArgs common
var nets []*netip.Prefix var nets []*netip.Prefix
@@ -170,9 +171,13 @@ func main() {
log.Panicln(err) log.Panicln(err)
} }
cmnArgs = args.VLSM.common cmnArgs = args.VLSM.common
if vlsmSizes, err = args.VLSM.AllSizes(); err != nil {
log.Panicln(err)
}
splitter = &netsplit.VLSMSplitter{ splitter = &netsplit.VLSMSplitter{
Ascending: args.VLSM.Asc, Ascending: args.VLSM.Asc,
PrefixLengths: args.VLSM.Sizes, Explicit: args.VLSM.Explicit,
PrefixLengths: vlsmSizes,
BaseSplitter: new(netsplit.BaseSplitter), BaseSplitter: new(netsplit.BaseSplitter),
} }
default: default:

View File

@@ -96,6 +96,9 @@ type tableFormatter struct {
NoBoldTitle bool NoBoldTitle bool
} }
// vlsmSize is a custom type to let us specify multiple sizes as a repeated or consolidated argument.
type vlsmSize string
type ReservedResults struct { type ReservedResults struct {
Opts CheckArgs Opts CheckArgs
Reserved map[netip.Prefix]*netsplit.IANAAddrNetResRecord Reserved map[netip.Prefix]*netsplit.IANAAddrNetResRecord

View File

@@ -2,7 +2,7 @@ package netsplit
import ( import (
"net/netip" "net/netip"
"sort" `sort`
"go4.org/netipx" "go4.org/netipx"
) )
@@ -42,17 +42,19 @@ func (v *VLSMSplitter) Split() (nets []*netip.Prefix, remaining *netipx.IPSet, e
return return
} }
sort.SliceStable( if !v.Explicit {
v.PrefixLengths, sort.SliceStable(
func(i, j int) (isBefore bool) { // We use a reverse sorting by default so we get larger prefixes at the beginning. v.PrefixLengths,
if v.Ascending { func(i, j int) (isBefore bool) { // We use a reverse sorting by default so we get larger prefixes at the beginning.
isBefore = v.PrefixLengths[i] > v.PrefixLengths[j] if v.Ascending {
} else { isBefore = v.PrefixLengths[i] > v.PrefixLengths[j]
isBefore = v.PrefixLengths[i] < v.PrefixLengths[j] } else {
} isBefore = v.PrefixLengths[i] < v.PrefixLengths[j]
return }
}, return
) },
)
}
pfxLen, _ = v.network.Mask.Size() pfxLen, _ = v.network.Mask.Size()
pfxLen8 = uint8(pfxLen) pfxLen8 = uint8(pfxLen)

View File

@@ -79,6 +79,13 @@ type VLSMSplitter struct {
You almost assuredly do not want to do this. You almost assuredly do not want to do this.
*/ */
Ascending bool Ascending bool
/*
Explicit, if true, will ignore Ascending completely and split in the explicit order of PrefixLengths.
This has the potential to be *extremely* wasteful of addressing space as the resulting blocks are
VERY unoptimized.
*/
Explicit bool
// PrefixLengths contains the prefix lengths of each subnet to split out from the network. // PrefixLengths contains the prefix lengths of each subnet to split out from the network.
PrefixLengths []uint8 `json:"prefixes" xml:"prefixes>prefix" yaml:"Prefix Lengths"` PrefixLengths []uint8 `json:"prefixes" xml:"prefixes>prefix" yaml:"Prefix Lengths"`
*BaseSplitter `json:"net" xml:"net,omitempty" yaml:"network,omitempty"` *BaseSplitter `json:"net" xml:"net,omitempty" yaml:"network,omitempty"`