mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-08 00:26:52 +00:00
wgengine/magicsock: support Geneve-encap'd Disco transmission (#15811)
Updates tailscale/corp#27502 Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
parent
51b17483ff
commit
61635f8670
@ -1111,7 +1111,7 @@ func (de *endpoint) sendDiscoPing(ep netip.AddrPort, discoKey key.DiscoPublic, t
|
|||||||
size = min(size, MaxDiscoPingSize)
|
size = min(size, MaxDiscoPingSize)
|
||||||
padding := max(size-discoPingSize, 0)
|
padding := max(size-discoPingSize, 0)
|
||||||
|
|
||||||
sent, _ := de.c.sendDiscoMessage(ep, de.publicKey, discoKey, &disco.Ping{
|
sent, _ := de.c.sendDiscoMessage(ep, nil, de.publicKey, discoKey, &disco.Ping{
|
||||||
TxID: [12]byte(txid),
|
TxID: [12]byte(txid),
|
||||||
NodeKey: de.c.publicKeyAtomic.Load(),
|
NodeKey: de.c.publicKeyAtomic.Load(),
|
||||||
Padding: padding,
|
Padding: padding,
|
||||||
|
@ -1602,23 +1602,60 @@ var debugIPv4DiscoPingPenalty = envknob.RegisterDuration("TS_DISCO_PONG_IPV4_DEL
|
|||||||
//
|
//
|
||||||
// If dst is a DERP IP:port, then dstKey must be non-zero.
|
// If dst is a DERP IP:port, then dstKey must be non-zero.
|
||||||
//
|
//
|
||||||
|
// If geneveVNI is non-nil, then the [disco.Message] will be preceded by a
|
||||||
|
// Geneve header with the supplied VNI set.
|
||||||
|
//
|
||||||
// The dstKey should only be non-zero if the dstDisco key
|
// The dstKey should only be non-zero if the dstDisco key
|
||||||
// unambiguously maps to exactly one peer.
|
// unambiguously maps to exactly one peer.
|
||||||
func (c *Conn) sendDiscoMessage(dst netip.AddrPort, dstKey key.NodePublic, dstDisco key.DiscoPublic, m disco.Message, logLevel discoLogLevel) (sent bool, err error) {
|
func (c *Conn) sendDiscoMessage(dst netip.AddrPort, geneveVNI *uint32, dstKey key.NodePublic, dstDisco key.DiscoPublic, m disco.Message, logLevel discoLogLevel) (sent bool, err error) {
|
||||||
isDERP := dst.Addr() == tailcfg.DerpMagicIPAddr
|
isDERP := dst.Addr() == tailcfg.DerpMagicIPAddr
|
||||||
if _, isPong := m.(*disco.Pong); isPong && !isDERP && dst.Addr().Is4() {
|
if _, isPong := m.(*disco.Pong); isPong && !isDERP && dst.Addr().Is4() {
|
||||||
time.Sleep(debugIPv4DiscoPingPenalty())
|
time.Sleep(debugIPv4DiscoPingPenalty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isRelayHandshakeMsg := false
|
||||||
|
switch m.(type) {
|
||||||
|
case *disco.BindUDPRelayEndpoint, *disco.BindUDPRelayEndpointAnswer:
|
||||||
|
isRelayHandshakeMsg = true
|
||||||
|
}
|
||||||
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
if c.closed {
|
if c.closed {
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
return false, errConnClosed
|
return false, errConnClosed
|
||||||
}
|
}
|
||||||
pkt := make([]byte, 0, 512) // TODO: size it correctly? pool? if it matters.
|
pkt := make([]byte, 0, 512) // TODO: size it correctly? pool? if it matters.
|
||||||
|
if geneveVNI != nil {
|
||||||
|
gh := packet.GeneveHeader{
|
||||||
|
Version: 0,
|
||||||
|
Protocol: packet.GeneveProtocolDisco,
|
||||||
|
VNI: *geneveVNI,
|
||||||
|
Control: isRelayHandshakeMsg,
|
||||||
|
}
|
||||||
|
pkt = append(pkt, make([]byte, packet.GeneveFixedHeaderLength)...)
|
||||||
|
err := gh.Encode(pkt)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
pkt = append(pkt, disco.Magic...)
|
pkt = append(pkt, disco.Magic...)
|
||||||
pkt = c.discoPublic.AppendTo(pkt)
|
pkt = c.discoPublic.AppendTo(pkt)
|
||||||
di := c.discoInfoLocked(dstDisco)
|
var di *discoInfo
|
||||||
|
if !isRelayHandshakeMsg {
|
||||||
|
di = c.discoInfoLocked(dstDisco)
|
||||||
|
} else {
|
||||||
|
// c.discoInfoLocked() caches [*discoInfo] for dstDisco. It assumes that
|
||||||
|
// dstDisco is a known Tailscale peer, and will be cleaned around
|
||||||
|
// network map changes. In the case of a relay handshake message,
|
||||||
|
// dstDisco belongs to a relay server with a disco key that is
|
||||||
|
// discovered at endpoint allocation time or [disco.CallMeMaybeVia]
|
||||||
|
// reception time. There is no clear ending to its lifetime, so we
|
||||||
|
// can't cache with the same strategy. Instead, generate the shared
|
||||||
|
// key on the fly for now.
|
||||||
|
di = &discoInfo{
|
||||||
|
sharedKey: c.discoPrivate.Shared(dstDisco),
|
||||||
|
}
|
||||||
|
}
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
|
||||||
if isDERP {
|
if isDERP {
|
||||||
@ -1943,7 +1980,7 @@ func (c *Conn) handlePingLocked(dm *disco.Ping, src netip.AddrPort, di *discoInf
|
|||||||
|
|
||||||
ipDst := src
|
ipDst := src
|
||||||
discoDest := di.discoKey
|
discoDest := di.discoKey
|
||||||
go c.sendDiscoMessage(ipDst, dstKey, discoDest, &disco.Pong{
|
go c.sendDiscoMessage(ipDst, nil, dstKey, discoDest, &disco.Pong{
|
||||||
TxID: dm.TxID,
|
TxID: dm.TxID,
|
||||||
Src: src,
|
Src: src,
|
||||||
}, discoVerboseLog)
|
}, discoVerboseLog)
|
||||||
@ -1988,12 +2025,12 @@ func (c *Conn) enqueueCallMeMaybe(derpAddr netip.AddrPort, de *endpoint) {
|
|||||||
for _, ep := range c.lastEndpoints {
|
for _, ep := range c.lastEndpoints {
|
||||||
eps = append(eps, ep.Addr)
|
eps = append(eps, ep.Addr)
|
||||||
}
|
}
|
||||||
go de.c.sendDiscoMessage(derpAddr, de.publicKey, epDisco.key, &disco.CallMeMaybe{MyNumber: eps}, discoLog)
|
go de.c.sendDiscoMessage(derpAddr, nil, de.publicKey, epDisco.key, &disco.CallMeMaybe{MyNumber: eps}, discoLog)
|
||||||
if debugSendCallMeUnknownPeer() {
|
if debugSendCallMeUnknownPeer() {
|
||||||
// Send a callMeMaybe packet to a non-existent peer
|
// Send a callMeMaybe packet to a non-existent peer
|
||||||
unknownKey := key.NewNode().Public()
|
unknownKey := key.NewNode().Public()
|
||||||
c.logf("magicsock: sending CallMeMaybe to unknown peer per TS_DEBUG_SEND_CALLME_UNKNOWN_PEER")
|
c.logf("magicsock: sending CallMeMaybe to unknown peer per TS_DEBUG_SEND_CALLME_UNKNOWN_PEER")
|
||||||
go de.c.sendDiscoMessage(derpAddr, unknownKey, epDisco.key, &disco.CallMeMaybe{MyNumber: eps}, discoLog)
|
go de.c.sendDiscoMessage(derpAddr, nil, unknownKey, epDisco.key, &disco.CallMeMaybe{MyNumber: eps}, discoLog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user