Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3763 from weaveworks/no-lock-round-send
Browse files Browse the repository at this point in the history
Move send of ipsec message outside lock
  • Loading branch information
bboreham authored Mar 5, 2020
2 parents 599b99a + ca0498b commit 709f820
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 19 deletions.
22 changes: 9 additions & 13 deletions net/ipsec/ipsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func New(log *logrus.Logger) (*IPSec, error) {

// InitSALocal initializes inbound ipsec from remotePeer and triggers
// the initialization on remotePeer.
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte, initRemote func([]byte) error) error {
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte) ([]byte, error) {
// ID of inbound SPI
spiID := getSPIId(remotePeer, localPeer, connUID)

Expand All @@ -95,17 +95,17 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
// Derive SA key
nonce, err := genNonce()
if err != nil {
return errors.Wrap(err, "generate nonce")
return nil, errors.Wrap(err, "generate nonce")
}
key, err := deriveKey(sessionKey[:], nonce, localPeer)
if err != nil {
return errors.Wrap(err, "derive key")
return nil, errors.Wrap(err, "derive key")
}

// Allocate SA
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
return nil, errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
}

// Use SPI generated by the kernel. The kernel ensures {dstIP, spi} to
Expand All @@ -117,28 +117,24 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
// Create SA
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); err == nil {
if err := netlink.XfrmStateUpdate(sa); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
return nil, errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
}
} else {
return errors.Wrap(err, "new xfrm state (in)")
return nil, errors.Wrap(err, "new xfrm state (in)")
}

// Install iptables rules
if err := ipsec.installDropNonEncrypted(localIP, remoteIP, udpPort, spi); err != nil {
return errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
return nil, errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
}

si := spiInfo{spi: spi, isDirOut: false}
ipsec.spiInfo[spiID] = si
ipsec.spis[spi] = &si

// Trigger the initialization on the remote peer
// Generate the message to trigger initialization on the remote peer
msg := &msgInitSARemote{nonce, spi}
if err := initRemote(msg.serialize()); err != nil {
return errors.Wrap(err, "send InitSARemote")
}

return nil
return msg.serialize(), nil
}

// InitSARemote initializes outbound ipsec to remotePeer.
Expand Down
20 changes: 14 additions & 6 deletions router/fastdp.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) {
// The netdev interface is down, so most likely bringing it up
// has failed due to the UDP port being in use.
if err := fastdp.dp.DeleteVport(vxlanVportID); err != nil {
log.Warning("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
log.Warningf("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
}
return 0, odp.NetlinkError(syscall.EADDRINUSE)
}
Expand Down Expand Up @@ -654,27 +654,26 @@ func (fwd *fastDatapathForwarder) logPrefix() string {

func (fwd *fastDatapathForwarder) Confirm() {
fwd.lock.Lock()
defer fwd.lock.Unlock()

if fwd.confirmed {
log.Fatal(fwd.logPrefix(), "already confirmed")
}

var controlMsg []byte
if fwd.fastdp.ipsec != nil && fwd.sessionKey != nil {
fwd.isEncrypted = true
log.Info("Setting up IPsec between ", fwd.fastdp.localPeer, " and ", fwd.remotePeer)
err := fwd.fastdp.ipsec.InitSALocal(
var err error
controlMsg, err = fwd.fastdp.ipsec.InitSALocal(
fwd.fastdp.localPeer.Name, fwd.remotePeer.Name, fwd.connUID,
net.IP(fwd.localIP[:]), fwd.remoteAddr.IP,
fwd.remoteAddr.Port,
fwd.sessionKey,
func(msg []byte) error {
return fwd.sendControlMsg(FastDatapathCryptoInitSARemote, msg)
},
)
if err != nil {
log.Error(fwd.logPrefix(), "ipsec init SA local failed: ", err)
fwd.handleError(err)
fwd.lock.Unlock()
return
}
}
Expand All @@ -692,6 +691,15 @@ func (fwd *fastDatapathForwarder) Confirm() {
}

fwd.heartbeatTimeout = time.NewTimer(HeartbeatTimeout)

fwd.lock.Unlock() // unlock before calling send() which may block

if err := fwd.sendControlMsg(FastDatapathCryptoInitSARemote, controlMsg); err != nil {
log.Error(fwd.logPrefix(), "ipsec send InitSARemote failed: ", err)
fwd.handleError(err)
return
}

go fwd.doHeartbeats()
}

Expand Down

0 comments on commit 709f820

Please sign in to comment.