Shard VPN fabric session streams
This commit is contained in:
@@ -3149,13 +3149,18 @@ func heartbeatPayload(cfg config.Config, identity state.Identity, meshState *syn
|
||||
}
|
||||
if cfg.VPNFabricSessionTransportEnabled {
|
||||
report := map[string]any{
|
||||
"schema_version": "rap.vpn_fabric_session_transport_report.v1",
|
||||
"enabled": true,
|
||||
"transport": "fabric_session_binary_frames",
|
||||
"carriers": []string{"quic", "websocket"},
|
||||
"packet_payload": "rap.vpn_packet_batch.fabric.v1",
|
||||
"gated": true,
|
||||
"observed_at": observedAt.UTC().Format(time.RFC3339Nano),
|
||||
"schema_version": "rap.vpn_fabric_session_transport_report.v1",
|
||||
"enabled": true,
|
||||
"transport": "fabric_session_binary_frames",
|
||||
"carriers": []string{"quic", "websocket"},
|
||||
"packet_payload": "rap.vpn_packet_batch.fabric.v1",
|
||||
"gated": true,
|
||||
"stream_shards_per_class": cfg.VPNFabricSessionStreamShards,
|
||||
"stream_classes": []string{
|
||||
vpnruntime.FabricTrafficClassInteractive,
|
||||
vpnruntime.FabricTrafficClassBulk,
|
||||
},
|
||||
"observed_at": observedAt.UTC().Format(time.RFC3339Nano),
|
||||
}
|
||||
if meshState != nil && meshState.VPNFabricTransport != nil {
|
||||
report["peer_sessions"] = meshState.VPNFabricTransport.Snapshot()
|
||||
@@ -3174,6 +3179,7 @@ func heartbeatPayload(cfg config.Config, identity state.Identity, meshState *syn
|
||||
payload.Metadata["vpn_fabric_session_transport_report"] = report
|
||||
payload.Capabilities["vpn_fabric_session_transport"] = true
|
||||
payload.Capabilities["vpn_packet_batch_binary_frames"] = true
|
||||
payload.Capabilities["vpn_fabric_session_stream_shards"] = true
|
||||
if meshState != nil && meshState.VPNFabricEndpointObservations != nil {
|
||||
payload.Metadata["vpn_fabric_endpoint_health_report"] = meshState.VPNFabricEndpointObservations.Report(observedAt, maxVPNFabricEndpointHealthReportEntries)
|
||||
} else {
|
||||
@@ -5151,7 +5157,7 @@ func fabricGatewayTransportForAssignment(ctx context.Context, cfg config.Config,
|
||||
return nil
|
||||
}
|
||||
if cfg.VPNFabricSessionTransportEnabled {
|
||||
if transport := fabricSessionGatewayTransportForAssignment(ctx, identity, assignment, meshState, nextHop); transport != nil {
|
||||
if transport := fabricSessionGatewayTransportForAssignment(ctx, cfg, identity, assignment, meshState, nextHop); transport != nil {
|
||||
return transport
|
||||
}
|
||||
}
|
||||
@@ -5170,7 +5176,7 @@ func fabricGatewayTransportForAssignment(ctx context.Context, cfg config.Config,
|
||||
}
|
||||
}
|
||||
|
||||
func fabricSessionGatewayTransportForAssignment(ctx context.Context, identity state.Identity, assignment client.NodeVPNAssignment, meshState *syntheticMeshState, nextHop string) vpnruntime.PacketTransport {
|
||||
func fabricSessionGatewayTransportForAssignment(ctx context.Context, cfg config.Config, identity state.Identity, assignment client.NodeVPNAssignment, meshState *syntheticMeshState, nextHop string) vpnruntime.PacketTransport {
|
||||
if meshState == nil || meshState.VPNFabricInbox == nil || assignment.VPNConnectionID == "" || nextHop == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -5224,15 +5230,8 @@ func fabricSessionGatewayTransportForAssignment(ctx context.Context, identity st
|
||||
log.Printf("vpn fabric session candidate skipped: vpn_connection_id=%s next_hop=%s candidate=%d endpoint=%s transport=%s reason=%s error=%v", assignment.VPNConnectionID, nextHop, index, selectedTarget.Endpoint, selectedTarget.Transport, reason, err)
|
||||
continue
|
||||
}
|
||||
streamID := uint64(time.Now().UnixNano())
|
||||
if streamID == 0 {
|
||||
streamID = 1
|
||||
}
|
||||
if err := session.Send(dialCtx, fabricproto.Frame{
|
||||
Type: fabricproto.FrameOpenStream,
|
||||
StreamID: streamID,
|
||||
TrafficClass: fabricproto.TrafficClassInteractive,
|
||||
}); err != nil {
|
||||
streamIDsByClass, streamID, err := openVPNFabricSessionStreams(dialCtx, session, cfg.VPNFabricSessionStreamShards)
|
||||
if err != nil {
|
||||
cancel()
|
||||
_ = session.Close()
|
||||
meshState.VPNFabricSessionDialStats.ObserveCandidateFailure("stream_open_failed")
|
||||
@@ -5245,14 +5244,14 @@ func fabricSessionGatewayTransportForAssignment(ctx context.Context, identity st
|
||||
meshState.VPNFabricEndpointObservations.ObserveSuccess(selectedTarget.EndpointID, time.Since(startedAt))
|
||||
log.Printf("vpn fabric session transport selected: vpn_connection_id=%s next_hop=%s candidate=%d endpoint=%s transport=%s pinned_cert=%t fallback_candidates=%d", assignment.VPNConnectionID, nextHop, index, selectedTarget.Endpoint, selectedTarget.Transport, selectedTarget.PeerCertSHA256 != "", len(targets)-index-1)
|
||||
return &vpnruntime.FabricSessionPacketTransport{
|
||||
Sender: session,
|
||||
Receiver: session,
|
||||
Inbox: meshState.VPNFabricInbox,
|
||||
StreamID: streamID,
|
||||
VPNConnectionID: assignment.VPNConnectionID,
|
||||
SendDirection: vpnruntime.FabricDirectionGatewayToClient,
|
||||
ReceiveDirection: vpnruntime.FabricDirectionClientToGateway,
|
||||
TrafficClass: vpnruntime.FabricTrafficClassInteractive,
|
||||
Sender: session,
|
||||
Receiver: session,
|
||||
Inbox: meshState.VPNFabricInbox,
|
||||
StreamID: streamID,
|
||||
StreamIDsByTrafficClass: streamIDsByClass,
|
||||
VPNConnectionID: assignment.VPNConnectionID,
|
||||
SendDirection: vpnruntime.FabricDirectionGatewayToClient,
|
||||
ReceiveDirection: vpnruntime.FabricDirectionClientToGateway,
|
||||
}
|
||||
}
|
||||
meshState.VPNFabricSessionDialStats.ObserveAllCandidatesFailed()
|
||||
@@ -5260,6 +5259,51 @@ func fabricSessionGatewayTransportForAssignment(ctx context.Context, identity st
|
||||
return nil
|
||||
}
|
||||
|
||||
func openVPNFabricSessionStreams(ctx context.Context, session mesh.FabricTransportSession, shards int) (map[string][]uint64, uint64, error) {
|
||||
if session == nil {
|
||||
return nil, 0, mesh.ErrForwardRuntimeUnavailable
|
||||
}
|
||||
if shards <= 0 {
|
||||
shards = 4
|
||||
}
|
||||
if shards > 64 {
|
||||
shards = 64
|
||||
}
|
||||
base := uint64(time.Now().UnixNano())
|
||||
if base == 0 {
|
||||
base = 1
|
||||
}
|
||||
classes := []struct {
|
||||
name string
|
||||
trafficClass fabricproto.TrafficClass
|
||||
}{
|
||||
{name: vpnruntime.FabricTrafficClassInteractive, trafficClass: fabricproto.TrafficClassInteractive},
|
||||
{name: vpnruntime.FabricTrafficClassBulk, trafficClass: fabricproto.TrafficClassBulk},
|
||||
}
|
||||
out := make(map[string][]uint64, len(classes))
|
||||
var primary uint64
|
||||
for classIndex, class := range classes {
|
||||
for shard := 0; shard < shards; shard++ {
|
||||
streamID := base + uint64(classIndex*shards+shard)
|
||||
if streamID == 0 {
|
||||
streamID = uint64(classIndex*shards + shard + 1)
|
||||
}
|
||||
if err := session.Send(ctx, fabricproto.Frame{
|
||||
Type: fabricproto.FrameOpenStream,
|
||||
StreamID: streamID,
|
||||
TrafficClass: class.trafficClass,
|
||||
}); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if primary == 0 {
|
||||
primary = streamID
|
||||
}
|
||||
out[class.name] = append(out[class.name], streamID)
|
||||
}
|
||||
}
|
||||
return out, primary, nil
|
||||
}
|
||||
|
||||
func fabricSessionOpenFailureReason(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user