pkg/mesh: fix panic in graph

Commit 4d00bc56fe introduced a bug in the
Kilo graph generation logic. This commit used the WireGuard CIDR from
the topology struct as the graph title, however this field is nil
whenever the selected node is not a leader, causing the program to
panic.

This commit changes the meaning of the topology struct's wireGuardCIDR
field so that the field is always defined and the normalized value will
always be equal to the Kilo subnet CIDR. When the selected node is a
leader node, then the field's IP will be the IP allocated to the node
within the subnet. This effectively prevents the program from panicking.

Signed-off-by: Lucas Servén Marín <lserven@gmail.com>
This commit is contained in:
Lucas Servén Marín 2021-03-25 02:59:54 +01:00
parent dc34682909
commit d1948acd77
No known key found for this signature in database
GPG Key ID: 586FEAF680DA74AD
4 changed files with 12 additions and 6 deletions

View File

@ -27,7 +27,7 @@ import (
func (t *Topology) Dot() (string, error) {
g := gographviz.NewGraph()
g.Name = "kilo"
if err := g.AddAttr("kilo", string(gographviz.Label), graphEscape(t.wireGuardCIDR.String())); err != nil {
if err := g.AddAttr("kilo", string(gographviz.Label), graphEscape((&net.IPNet{IP: t.wireGuardCIDR.IP.Mask(t.wireGuardCIDR.Mask), Mask: t.wireGuardCIDR.Mask}).String())); err != nil {
return "", fmt.Errorf("failed to add label to graph")
}
if err := g.AddAttr("kilo", string(gographviz.LabelLOC), "t"); err != nil {

View File

@ -477,7 +477,11 @@ func (m *Mesh) applyTopology() {
return
}
// Update the node's WireGuard IP.
m.wireGuardIP = t.wireGuardCIDR
if t.leader {
m.wireGuardIP = t.wireGuardCIDR
} else {
m.wireGuardIP = nil
}
conf := t.Conf()
buf, err := conf.Bytes()
if err != nil {

View File

@ -50,8 +50,10 @@ type Topology struct {
// subnet is the Pod subnet of the local node.
subnet *net.IPNet
// wireGuardCIDR is the allocated CIDR of the WireGuard
// interface of the local node. If the local node is not
// the leader, then it is nil.
// interface of the local node within the Kilo subnet.
// If the local node is not the leader of a location, then
// the IP is the 0th address in the subnet, i.e. the CIDR
// is equal to the Kilo subnet.
wireGuardCIDR *net.IPNet
}
@ -104,7 +106,7 @@ func NewTopology(nodes map[string]*Node, peers map[string]*Peer, granularity Gra
localLocation = nodeLocationPrefix + hostname
}
t := Topology{key: key, port: port, hostname: hostname, location: localLocation, persistentKeepalive: persistentKeepalive, privateIP: nodes[hostname].InternalIP, subnet: nodes[hostname].Subnet}
t := Topology{key: key, port: port, hostname: hostname, location: localLocation, persistentKeepalive: persistentKeepalive, privateIP: nodes[hostname].InternalIP, subnet: nodes[hostname].Subnet, wireGuardCIDR: subnet}
for location := range topoMap {
// Sort the location so the result is stable.
sort.Slice(topoMap[location], func(i, j int) bool {

View File

@ -215,7 +215,7 @@ func TestNewTopology(t *testing.T) {
location: logicalLocationPrefix + nodes["b"].Location,
subnet: nodes["c"].Subnet,
privateIP: nodes["c"].InternalIP,
wireGuardCIDR: nil,
wireGuardCIDR: DefaultKiloSubnet,
segments: []*segment{
{
allowedIPs: []*net.IPNet{nodes["a"].Subnet, nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},