switch to github.com/mdlayher/netlink

this gives us access to the socket receive buffer size and it saves 2mb
binary size.
This commit is contained in:
lemmi 2020-01-23 04:07:29 +01:00
parent 8f0e46f37f
commit 05bff7f5ad
1 changed files with 61 additions and 31 deletions

92
main.go
View File

@ -15,7 +15,8 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/vishvananda/netlink" "github.com/jsimonetti/rtnetlink"
"github.com/mdlayher/netlink"
) )
var ( var (
@ -65,25 +66,31 @@ func newRouteStats() *routeStats {
} }
} }
func (rs *routeStats) update(ru netlink.RouteUpdate) { func DstIPNet(rm rtnetlink.RouteMessage) *net.IPNet {
rs.Lock() var zeros int
defer rs.Unlock() switch rm.Family {
case unix.AF_INET:
switch ru.Type { zeros = 32
case unix.RTM_NEWROUTE: case unix.AF_INET6:
rs.add(ru) zeros = 128
case unix.RTM_DELROUTE:
rs.del(ru)
default: default:
fmt.Fprintf(os.Stderr, "Unknown route type %d\n", ru.Type) fmt.Fprintf(os.Stderr, "unexpected family %q", rm.Family)
}
return &net.IPNet{
IP: rm.Attributes.Dst,
Mask: net.CIDRMask(int(rm.DstLength), zeros),
} }
} }
func (rs *routeStats) add(ru netlink.RouteUpdate) { func (rs *routeStats) add(rm rtnetlink.RouteMessage) {
key := ru.Route.Dst.String() rs.Lock()
defer rs.Unlock()
dst := DstIPNet(rm)
key := dst.String()
r := rs.stats[key] r := rs.stats[key]
if r == nil { if r == nil {
r = &route{Dst: ru.Route.Dst} r = &route{Dst: dst}
} }
r.Counter++ r.Counter++
if r.UnreachableSince == nil { if r.UnreachableSince == nil {
@ -93,11 +100,15 @@ func (rs *routeStats) add(ru netlink.RouteUpdate) {
rs.stats[key] = r rs.stats[key] = r
} }
func (rs *routeStats) del(ru netlink.RouteUpdate) { func (rs *routeStats) del(rm rtnetlink.RouteMessage) {
key := ru.Route.Dst.String() rs.Lock()
defer rs.Unlock()
dst := DstIPNet(rm)
key := dst.String()
r := rs.stats[key] r := rs.stats[key]
if r == nil { if r == nil {
r = &route{Dst: ru.Route.Dst} r = &route{Dst: dst}
return return
} }
r.UnreachableDuration += time.Since(*r.UnreachableSince) r.UnreachableDuration += time.Since(*r.UnreachableSince)
@ -129,25 +140,44 @@ func (rs *routeStats) getLongest() []route {
} }
func monitor(done <-chan struct{}, rs *routeStats) { func monitor(done <-chan struct{}, rs *routeStats) {
rups := make(chan netlink.RouteUpdate, 64) c, err := netlink.Dial(unix.NETLINK_ROUTE, &netlink.Config{
opts := netlink.RouteSubscribeOptions{ Groups: 1<<(unix.RTNLGRP_IPV4_ROUTE-1) | 1<<(unix.RTNLGRP_IPV6_ROUTE-1),
ErrorCallback: func(err error) { })
fmt.Fprintf(os.Stderr, "%s\n", err, err) if err != nil {
},
}
if err := netlink.RouteSubscribeWithOptions(rups, done, opts); err != nil {
log.Fatal(err) log.Fatal(err)
} }
for ru := range rups { go func() {
if ru.Route.Type != unix.RTN_UNREACHABLE { <-done
continue c.Close()
}()
if err = c.SetReadBuffer(16 * 1048576); err != nil {
log.Fatal(err)
}
for {
ms, err := c.Receive()
if err != nil {
log.Println(err)
} }
// show unly babel routes
if ru.Route.Protocol != 42 { for _, m := range ms {
continue rm := rtnetlink.RouteMessage{}
if err = rm.UnmarshalBinary(m.Data); err != nil {
log.Fatal(err)
}
if rm.Type != unix.RTN_UNREACHABLE ||
rm.Protocol != 42 {
continue
}
switch m.Header.Type {
case unix.RTM_NEWROUTE:
rs.add(rm)
case unix.RTM_DELROUTE:
rs.del(rm)
}
} }
rs.update(ru)
} }
} }