Skip to content

Commit

Permalink
Move IP refcounting into the layer2 package.
Browse files Browse the repository at this point in the history
BGP mode does its own "refcounting" through announcement deduplication.

Fixes #295

(cherry picked from commit 5cd15b1)
  • Loading branch information
danderson committed Aug 17, 2018
1 parent 253d87f commit d25ae6b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 20 deletions.
33 changes: 25 additions & 8 deletions internal/layer2/announcer.go
Expand Up @@ -13,18 +13,20 @@ type Announce struct {
logger log.Logger

sync.RWMutex
arps map[int]*arpResponder
ndps map[int]*ndpResponder
ips map[string]net.IP // map containing IPs we should announce
arps map[int]*arpResponder
ndps map[int]*ndpResponder
ips map[string]net.IP // svcName -> IP
ipRefcnt map[string]int // ip.String() -> number of uses
}

// New returns an initialized Announce.
func New(l log.Logger) (*Announce, error) {
ret := &Announce{
logger: l,
arps: map[int]*arpResponder{},
ndps: map[int]*ndpResponder{},
ips: make(map[string]net.IP),
logger: l,
arps: map[int]*arpResponder{},
ndps: map[int]*ndpResponder{},
ips: map[string]net.IP{},
ipRefcnt: map[string]int{},
}
go ret.interfaceScan()

Expand Down Expand Up @@ -174,6 +176,13 @@ func (a *Announce) SetBalancer(name string, ip net.IP) {
return
}

a.ipRefcnt[ip.String()]++
if a.ipRefcnt[ip.String()] > 1 {
// Multiple services are using this IP, so there's nothing
// else to do right now.
return
}

for _, client := range a.ndps {
if err := client.Watch(ip); err != nil {
a.logger.Log("op", "watchMulticastGroup", "error", err, "ip", ip, "msg", "failed to watch NDP multicast group for IP, NDP responder will not respond to requests for this address")
Expand All @@ -182,6 +191,7 @@ func (a *Announce) SetBalancer(name string, ip net.IP) {

a.ips[name] = ip
go a.spam(name)

}

// DeleteBalancer deletes an address from the set of addresses we should announce.
Expand All @@ -193,14 +203,21 @@ func (a *Announce) DeleteBalancer(name string) {
if !ok {
return
}
delete(a.ips, name)

a.ipRefcnt[ip.String()]--
if a.ipRefcnt[ip.String()] > 0 {
// Another service is still using this IP, don't touch any
// more things.
return
}

for _, client := range a.ndps {
if err := client.Unwatch(ip); err != nil {
a.logger.Log("op", "unwatchMulticastGroup", "error", err, "ip", ip, "msg", "failed to unwatch NDP multicast group for IP")
}
}

delete(a.ips, name)
}

// AnnounceName returns true when we have an announcement under name.
Expand Down
17 changes: 5 additions & 12 deletions speaker/main.go
Expand Up @@ -111,7 +111,6 @@ type controller struct {
protocols map[config.Proto]Protocol
announced map[string]config.Proto // service name -> protocol advertising it
svcIP map[string]net.IP // service name -> assigned IP
ipRefcnt map[string]int // IP string -> number of consumers
}

type controllerConfig struct {
Expand Down Expand Up @@ -147,7 +146,6 @@ func newController(cfg controllerConfig) (*controller, error) {
protocols: protocols,
announced: map[string]config.Proto{},
svcIP: map[string]net.IP{},
ipRefcnt: map[string]int{},
}

return ret, nil
Expand Down Expand Up @@ -220,7 +218,6 @@ func (c *controller) SetBalancer(l log.Logger, name string, svc *v1.Service, eps
if c.announced[name] == "" {
c.announced[name] = pool.Protocol
c.svcIP[name] = lbIP
c.ipRefcnt[lbIP.String()]++
}

announcing.With(prometheus.Labels{
Expand All @@ -240,8 +237,11 @@ func (c *controller) deleteBalancer(l log.Logger, name, reason string) bool {
return true
}

c.ipRefcnt[c.svcIP[name].String()]--
ref := c.ipRefcnt[c.svcIP[name].String()]
if err := c.protocols[proto].DeleteBalancer(l, name, reason); err != nil {
l.Log("op", "deleteBalancer", "error", err, "msg", "failed to clear balancer state")
return false
}

announcing.Delete(prometheus.Labels{
"protocol": string(proto),
"service": name,
Expand All @@ -251,13 +251,6 @@ func (c *controller) deleteBalancer(l log.Logger, name, reason string) bool {
delete(c.announced, name)
delete(c.svcIP, name)

if ref == 0 {
if err := c.protocols[proto].DeleteBalancer(l, name, reason); err != nil {
l.Log("op", "deleteBalancer", "error", err, "msg", "failed to clear balancer state")
return false
}
}

l.Log("event", "serviceWithdrawn", "ip", c.svcIP[name], "reason", reason, "msg", "withdrawing service announcement")

return true
Expand Down

0 comments on commit d25ae6b

Please sign in to comment.