Skip to content

Commit

Permalink
Generate a router-id from a hash on the hostname as fallback
Browse files Browse the repository at this point in the history
This may be necessary in a true ipv6-only cluster.
  • Loading branch information
Lars Ekman authored and danderson committed Mar 1, 2019
1 parent 7bda4e8 commit 34ae479
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 13 deletions.
26 changes: 16 additions & 10 deletions internal/bgp/bgp.go
@@ -1,10 +1,12 @@
package bgp // import "go.universe.tf/metallb/internal/bgp"

import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"io"
"io/ioutil"
"net"
Expand All @@ -25,6 +27,7 @@ var errClosed = errors.New("session closed")
type Session struct {
asn uint32
routerID net.IP // May be nil, meaning "derive from context"
myNode string
addr string
peerASN uint32
holdTime time.Duration
Expand Down Expand Up @@ -184,11 +187,7 @@ func (s *Session) connect() error {

routerID := s.routerID
if routerID == nil {
routerID = getRouterID(s.defaultNextHop)
if routerID == nil {
conn.Close()
return fmt.Errorf("cannot automatically derive router ID for IPv6 connection to %q", s.addr)
}
routerID = getRouterID(s.defaultNextHop, s.myNode)
}

if err = sendOpen(conn, s.asn, routerID, s.holdTime); err != nil {
Expand Down Expand Up @@ -235,16 +234,22 @@ func (s *Session) connect() error {
return nil
}

func hashRouterId(hostname string) net.IP {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, crc32.ChecksumIEEE([]byte(hostname)))
return net.IP(buf.Bytes())
}

// Ipv4; Use the address as-is.
// Ipv6; Pick the first ipv4 address on the same interface as the address
func getRouterID(addr net.IP) net.IP {
func getRouterID(addr net.IP, myNode string) net.IP {
if addr.To4() != nil {
return addr
}

ifaces, err := net.Interfaces()
if err != nil {
return nil
return hashRouterId(myNode)
}
for _, i := range ifaces {
addrs, err := i.Addrs()
Expand Down Expand Up @@ -274,12 +279,12 @@ func getRouterID(addr net.IP) net.IP {
if ip.To4() != nil {
return ip
}
return nil
}
return hashRouterId(myNode)
}
}
}
return nil
return hashRouterId(myNode)
}

// sendKeepalives sends BGP KEEPALIVE packets at the negotiated rate
Expand Down Expand Up @@ -339,11 +344,12 @@ func (s *Session) sendKeepalive() error {
//
// The session will immediately try to connect and synchronize its
// local state with the peer.
func New(l log.Logger, addr string, asn uint32, routerID net.IP, peerASN uint32, holdTime time.Duration, password string) (*Session, error) {
func New(l log.Logger, addr string, asn uint32, routerID net.IP, peerASN uint32, holdTime time.Duration, password string, myNode string) (*Session, error) {
ret := &Session{
addr: addr,
asn: asn,
routerID: routerID.To4(),
myNode: myNode,
peerASN: peerASN,
holdTime: holdTime,
logger: log.With(l, "peer", addr, "localASN", asn, "peerASN", peerASN),
Expand Down
6 changes: 3 additions & 3 deletions speaker/bgp_controller.go
Expand Up @@ -184,7 +184,7 @@ func (c *bgpController) syncPeers(l log.Logger) error {
if p.cfg.RouterID != nil {
routerID = p.cfg.RouterID
}
s, err := newBGP(c.logger, net.JoinHostPort(p.cfg.Addr.String(), strconv.Itoa(int(p.cfg.Port))), p.cfg.MyASN, routerID, p.cfg.ASN, p.cfg.HoldTime, p.cfg.Password)
s, err := newBGP(c.logger, net.JoinHostPort(p.cfg.Addr.String(), strconv.Itoa(int(p.cfg.Port))), p.cfg.MyASN, routerID, p.cfg.ASN, p.cfg.HoldTime, p.cfg.Password, c.myNode)
if err != nil {
l.Log("op", "syncPeers", "error", err, "peer", p.cfg.Addr, "msg", "failed to create BGP session")
errs++
Expand Down Expand Up @@ -286,6 +286,6 @@ func (c *bgpController) SetNode(l log.Logger, node *v1.Node) error {
return c.syncPeers(l)
}

var newBGP = func(logger log.Logger, addr string, myASN uint32, routerID net.IP, asn uint32, hold time.Duration, password string) (session, error) {
return bgp.New(logger, addr, myASN, routerID, asn, hold, password)
var newBGP = func(logger log.Logger, addr string, myASN uint32, routerID net.IP, asn uint32, hold time.Duration, password string, myNode string) (session, error) {
return bgp.New(logger, addr, myASN, routerID, asn, hold, password, myNode)
}

0 comments on commit 34ae479

Please sign in to comment.