Compare commits

...

3 Commits

3 changed files with 45 additions and 17 deletions

View File

@ -111,16 +111,12 @@
</figure>
</details>
<h2><code>{{ .Api.Root }}</code></h2>
<div id="control" hx-swap="none">
<button hx-get="/api/alloc/32">/32</button>
<button hx-get="/api/alloc/31">/31</button>
<button hx-get="/api/alloc/30">/30</button>
<button hx-get="/api/alloc/29">/29</button>
<button hx-get="/api/alloc/28">/28</button>
<button hx-get="/api/alloc/27">/27</button>
<button hx-get="/api/alloc/26">/26</button>
<button hx-get="/api/alloc/25">/25</button>
<button hx-get="/api/alloc/24">/24</button>
{{- range .Api.AllowedLengths }}
<button hx-get="/api/alloc/{{ . }}">/{{ . }}</button>
{{- end }}
</div>
{{ block "update" .Update }}<div id="updatemsg" class="card {{ .Type }}" hx-swap-oob="morph">{{ with .Content }}{{ . }}{{ end }}</div>{{ end }}
@ -154,7 +150,7 @@
{{- end }}
{{ block "used" .Api }}
<div id="state" hx-swap-oob="morph" hx-swap="none">
<h2>grouped</h2>
<h3>grouped</h3>
<div id="used-grouped">
{{- range .UsedGrouped }}
{{- $first := index . 0 }}
@ -170,7 +166,7 @@
{{ end -}}
</div>
<h2>all</h2>
<h3>all</h3>
<div id="used">
<table>
{{- range .Used }}

View File

@ -266,13 +266,21 @@ func (t *tree) Dot() string {
type DB struct {
sync.Mutex
provisions *tree
provisions *tree
allowedLengths []int
}
func NewDB(prefix string) *DB {
return &DB{provisions: &tree{prefix: netip.MustParsePrefix(prefix)}}
func NewDB(prefix string, allowedLengths ...int) *DB {
p := netip.MustParsePrefix(prefix)
if canonical := p.Masked(); p.Addr() != canonical.Addr() {
log.Fatalf("Prefix %q is not in canonical form, use: %q", p, canonical)
}
return &DB{provisions: &tree{prefix: p}, allowedLengths: allowedLengths}
}
func (db *DB) AllowedLengths() []int {
return slices.Clip(db.allowedLengths)
}
func (db *DB) Used() []netip.Prefix {
db.Lock()
defer db.Unlock()
@ -319,6 +327,9 @@ func (db *DB) All() []*tree {
})
return ret
}
func (db *DB) Dot() string {
return db.provisions.Dot()
}
func (db *DB) Alloc(bits int) (*tree, error) {
db.Lock()
defer db.Unlock()
@ -399,7 +410,7 @@ func prefixShape(p netip.Prefix) Rect {
return Rect{
Y: 0,
X: 0,
H: 1 << (bits / 2),
H: 1 << (bits / 2), // TODO: handle overflow for normal ipv6 subnet sizes :)
W: 1 << ((bits + 1) / 2),
}
}

25
main.go
View File

@ -4,6 +4,7 @@ import (
"embed"
"fmt"
"html/template"
"io"
"log"
"net/http"
"net/netip"
@ -30,9 +31,13 @@ func (s *server) setup() {
s.mux.HandleFunc("/api/used/", s.apiUsed)
s.mux.HandleFunc("/api/print/", s.apiPrint)
s.mux.HandleFunc("/api/treemap.dot", s.apiDot)
//s.mux.HandleFunc("/api/provision/", s.apiProvision)
s.ipdb = ipalloc.NewDB("10.83.46.0/23")
s.ipdb = ipalloc.NewDB("10.83.46.0/23", 32, 29, 28, 27, 26)
//s.ipdb = ipalloc.NewDB("fd43:5602:29bd:fffe::/64", 128, 127, 126)
//s.ipdb = ipalloc.NewDB("fd43:5602:29bd:ffff:ffff:ffff:0:0/96", 128, 127, 126)
//s.ipdb = ipalloc.NewDB("fd43:5602:29bd:ffff:ffff:ffff:ffff:0/112", 128)
s.tmpl = template.Must(template.ParseFS(webcontent, "index.html"))
}
@ -59,7 +64,23 @@ type UpdateMessage struct {
}
func (s *server) template(w http.ResponseWriter, r *http.Request) {
err := s.tmpl.Execute(w, PageContent{Api: s.ipdb, Treemap: s.ipdb.Treemap()})
err := s.tmpl.Execute(w,
PageContent{
Api: s.ipdb,
Update: UpdateMessage{
Type: "hint",
Content: template.HTML("&nbsp;"),
},
Treemap: s.ipdb.Treemap(),
},
)
if err != nil {
log.Println(err)
}
}
func (s *server) apiDot(w http.ResponseWriter, r *http.Request) {
_, err := io.WriteString(w, s.ipdb.Dot())
if err != nil {
log.Println(err)
}