Skip to content

Commit 3cd5716

Browse files
fix(spanner): update DirectPath detection logic to use ALTS credentials (#14288)
Switched the directpath_used metric logic to assert alts.AuthInfo on the gRPC peer context. This improves reliability over previous IP prefix matching, mapping more closely to standard gRPC practices across evolving DirectPath networks.
1 parent 370e0ed commit 3cd5716

4 files changed

Lines changed: 72 additions & 19 deletions

File tree

spanner/grpc_client.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ import (
3434
"google.golang.org/grpc/status"
3535
)
3636

37-
const (
38-
directPathIPV6Prefix = "[2001:4860:8040"
39-
directPathIPV4Prefix = "34.126"
40-
)
41-
4237
type contextKey string
4338

4439
const metricsTracerKey contextKey = "metricsTracer"

spanner/integration_test.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import (
5757
"google.golang.org/api/option/internaloption"
5858
"google.golang.org/grpc"
5959
"google.golang.org/grpc/codes"
60+
"google.golang.org/grpc/credentials/alts"
6061
"google.golang.org/grpc/credentials/insecure"
6162
"google.golang.org/grpc/peer"
6263
"google.golang.org/grpc/status"
@@ -6608,22 +6609,20 @@ func verifyDirectPathRemoteAddress(t *testing.T) {
66086609
return
66096610
}
66106611
if remoteIP, res := isDirectPathRemoteAddress(); !res {
6611-
if dpConfig.directPathIPv4Only {
6612-
t.Fatalf("Expect to access DirectPath via ipv4 only, but RPC was destined to %s", remoteIP)
6613-
} else {
6614-
t.Fatalf("Expect to access DirectPath via ipv4 or ipv6, but RPC was destined to %s", remoteIP)
6615-
}
6612+
t.Fatalf("Expect to access DirectPath via ALTS, but RPC was destined to %s", remoteIP)
66166613
}
66176614
}
66186615

66196616
func isDirectPathRemoteAddress() (_ string, _ bool) {
6620-
remoteIP := peerInfo.Addr.String()
6621-
// DirectPath ipv4-only can only use ipv4 traffic.
6622-
if dpConfig.directPathIPv4Only {
6623-
return remoteIP, strings.HasPrefix(remoteIP, directPathIPV4Prefix)
6617+
var remoteIP string
6618+
if peerInfo != nil && peerInfo.Addr != nil {
6619+
remoteIP = peerInfo.Addr.String()
6620+
}
6621+
isDP := false
6622+
if peerInfo != nil && peerInfo.AuthInfo != nil {
6623+
_, isDP = peerInfo.AuthInfo.(alts.AuthInfo)
66246624
}
6625-
// DirectPath ipv6 can use either ipv4 or ipv6 traffic.
6626-
return remoteIP, strings.HasPrefix(remoteIP, directPathIPV4Prefix) || strings.HasPrefix(remoteIP, directPathIPV6Prefix)
6625+
return remoteIP, isDP
66276626
}
66286627

66296628
// examineTraffic counts RPCs use DirectPath or CFE traffic.

spanner/metrics.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"google.golang.org/api/option"
3838
"google.golang.org/grpc"
3939
"google.golang.org/grpc/codes"
40+
"google.golang.org/grpc/credentials/alts"
4041
"google.golang.org/grpc/experimental/stats"
4142
"google.golang.org/grpc/peer"
4243
"google.golang.org/grpc/stats/opentelemetry"
@@ -533,9 +534,8 @@ func (o *opTracer) incrementAttemptCount() {
533534
// setDirectPathUsed sets whether DirectPath was used for the attempt.
534535
func (a *attemptTracer) setDirectPathUsed(ctx context.Context) {
535536
peerInfo, ok := peer.FromContext(ctx)
536-
if ok && peerInfo.Addr != nil {
537-
remoteIP := peerInfo.Addr.String()
538-
if strings.HasPrefix(remoteIP, directPathIPV4Prefix) || strings.HasPrefix(remoteIP, directPathIPV6Prefix) {
537+
if ok {
538+
if _, isALTS := peerInfo.AuthInfo.(alts.AuthInfo); isALTS {
539539
a.directPathUsed = true
540540
}
541541
}

spanner/metrics_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ import (
3131
"google.golang.org/genproto/googleapis/api/metric"
3232
"google.golang.org/grpc"
3333
"google.golang.org/grpc/codes"
34+
"google.golang.org/grpc/credentials/alts"
3435
"google.golang.org/grpc/credentials/insecure"
36+
"google.golang.org/grpc/peer"
3537
"google.golang.org/grpc/status"
3638
)
3739

@@ -314,3 +316,60 @@ func parseHex(hexStr string) (int64, error) {
314316
_, err := fmt.Sscanf(hexStr, "%x", &value)
315317
return value, err
316318
}
319+
320+
type mockALTSAuthInfo struct {
321+
alts.AuthInfo
322+
}
323+
324+
func (m mockALTSAuthInfo) AuthType() string { return "alts" }
325+
326+
type mockOtherAuthInfo struct{}
327+
328+
func (m mockOtherAuthInfo) AuthType() string { return "other" }
329+
330+
func TestSetDirectPathUsed(t *testing.T) {
331+
tests := []struct {
332+
name string
333+
peer *peer.Peer
334+
want bool
335+
}{
336+
{
337+
name: "ALTS AuthInfo",
338+
peer: &peer.Peer{
339+
AuthInfo: mockALTSAuthInfo{},
340+
},
341+
want: true,
342+
},
343+
{
344+
name: "Other AuthInfo",
345+
peer: &peer.Peer{
346+
AuthInfo: mockOtherAuthInfo{},
347+
},
348+
want: false,
349+
},
350+
{
351+
name: "No AuthInfo",
352+
peer: &peer.Peer{},
353+
want: false,
354+
},
355+
{
356+
name: "No Peer",
357+
peer: nil,
358+
want: false,
359+
},
360+
}
361+
362+
for _, tc := range tests {
363+
t.Run(tc.name, func(t *testing.T) {
364+
tracer := &attemptTracer{}
365+
ctx := context.Background()
366+
if tc.peer != nil {
367+
ctx = peer.NewContext(ctx, tc.peer)
368+
}
369+
tracer.setDirectPathUsed(ctx)
370+
if tracer.directPathUsed != tc.want {
371+
t.Errorf("setDirectPathUsed() = %v, want %v", tracer.directPathUsed, tc.want)
372+
}
373+
})
374+
}
375+
}

0 commit comments

Comments
 (0)