5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-10 06:20:26 +00:00

Cache crypto-key routes (until routing table changes)

This commit is contained in:
Neil Alexander 2018-11-05 17:31:10 +00:00
parent ec751e8cc7
commit 295e9c9a10
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944

View File

@ -16,6 +16,8 @@ type cryptokey struct {
enabled bool enabled bool
ipv4routes []cryptokey_route ipv4routes []cryptokey_route
ipv6routes []cryptokey_route ipv6routes []cryptokey_route
ipv4cache map[address]cryptokey_route
ipv6cache map[address]cryptokey_route
} }
type cryptokey_route struct { type cryptokey_route struct {
@ -27,6 +29,8 @@ func (c *cryptokey) init(core *Core) {
c.core = core c.core = core
c.ipv4routes = make([]cryptokey_route, 0) c.ipv4routes = make([]cryptokey_route, 0)
c.ipv6routes = make([]cryptokey_route, 0) c.ipv6routes = make([]cryptokey_route, 0)
c.ipv4cache = make(map[address]cryptokey_route, 0)
c.ipv6cache = make(map[address]cryptokey_route, 0)
} }
func (c *cryptokey) isEnabled() bool { func (c *cryptokey) isEnabled() bool {
@ -68,12 +72,20 @@ func (c *cryptokey) addRoute(cidr string, dest string) error {
subnet: *ipnet, subnet: *ipnet,
destination: boxPubKey, destination: boxPubKey,
}) })
// Sort so most specific routes are first // Sort so most specific routes are first
sort.Slice(c.ipv6routes, func(i, j int) bool { sort.Slice(c.ipv6routes, func(i, j int) bool {
im, _ := c.ipv6routes[i].subnet.Mask.Size() im, _ := c.ipv6routes[i].subnet.Mask.Size()
jm, _ := c.ipv6routes[j].subnet.Mask.Size() jm, _ := c.ipv6routes[j].subnet.Mask.Size()
return im > jm return im > jm
}) })
// Clear the cache as this route might change future routing
// Setting an empty slice keeps the memory whereas nil invokes GC
for k := range c.ipv6cache {
delete(c.ipv6cache, k)
}
return nil return nil
} }
} else if prefixsize == net.IPv4len*8 { } else if prefixsize == net.IPv4len*8 {
@ -83,28 +95,39 @@ func (c *cryptokey) addRoute(cidr string, dest string) error {
return errors.New("Unspecified error") return errors.New("Unspecified error")
} }
func (c *cryptokey) getPublicKeyForAddress(addr string) (boxPubKey, error) { func (c *cryptokey) getPublicKeyForAddress(addr address) (boxPubKey, error) {
ipaddr := net.ParseIP(addr) // Check if there's a cache entry for this addr
if route, ok := c.ipv6cache[addr]; ok {
var box boxPubKey
copy(box[:boxPubKeyLen], route.destination)
return box, nil
}
if ipaddr.To4() == nil { // No cache was found - start by converting the address into a net.IP
// IPv6 ip := make(net.IP, 16)
copy(ip[:16], addr[:])
// Check whether it's an IPv4 or an IPv6 address
if ip.To4() == nil {
// Check if we have a route. At this point c.ipv6routes should be
// pre-sorted so that the most specific routes are first
for _, route := range c.ipv6routes { for _, route := range c.ipv6routes {
if route.subnet.Contains(ipaddr) { // Does this subnet match the given IP?
if route.subnet.Contains(ip) {
// Cache the entry for future packets to get a faster lookup
c.ipv6cache[addr] = route
// Return the boxPubKey
var box boxPubKey var box boxPubKey
copy(box[:boxPubKeyLen], route.destination) copy(box[:boxPubKeyLen], route.destination)
return box, nil return box, nil
} }
} }
} else { } else {
// IPv4 // IPv4 isn't supported yet
return boxPubKey{}, errors.New("IPv4 not supported at this time") return boxPubKey{}, errors.New("IPv4 not supported at this time")
/*
for _, route := range c.ipv4routes {
if route.subnet.Contains(ipaddr) {
return route.destination, nil
}
}
*/
} }
return boxPubKey{}, errors.New(fmt.Sprintf("No route to %s", addr))
// No route was found if we got to this point
return boxPubKey{}, errors.New(fmt.Sprintf("No route to %s", ip.String()))
} }