shared: add independent IPv4 and IPv6 collection [CI]
This commit is contained in:
1 parent
c974a7dddb
commit
0eda0600cc
60 files changed
+699
-137
No files matched your search
@@ -69,6 +69,7 @@ public static class ChunkFinalizer
|
||||
Phase = source.Phase,
|
||||
AgentId = agent,
|
||||
ProbeId = source.ProbeId,
|
||||
IpVersion = source.IpVersion,
|
||||
Target = null,
|
||||
Params = new Dictionary<string, JsonElement>(resolvedParams),
|
||||
Port = port,
|
||||
|
||||
@@ -39,7 +39,7 @@ public sealed class TcpLink : IDisposable
|
||||
/// </summary>
|
||||
public static async Task<TcpLink> OpenAsync(BlockEnv env, int port, bool tls, uint streamId, bool sendAuth, CancellationToken ct)
|
||||
{
|
||||
var client = new TcpClient { NoDelay = true };
|
||||
var client = new TcpClient(env.PeerAddress!.AddressFamily) { NoDelay = true };
|
||||
try
|
||||
{
|
||||
long start = env.Clock.NowUs();
|
||||
@@ -153,6 +153,11 @@ public sealed class TcpAcceptor
|
||||
foreach (int port in _ports)
|
||||
{
|
||||
var listener = new TcpListener(_bind, port);
|
||||
if (_bind.Equals(IPAddress.IPv6Any))
|
||||
{
|
||||
listener.Server.DualMode = true;
|
||||
}
|
||||
|
||||
listener.Start(128);
|
||||
_listeners.Add(listener);
|
||||
bound.Add(((IPEndPoint)listener.LocalEndpoint).Port);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace MoShiro.Protocol;
|
||||
|
||||
/// <summary>测量路径的地址族。旧契约缺省为 IPv4;IPv6 使用独立的线路和序列。</summary>
|
||||
public static class IpVersions
|
||||
{
|
||||
public const string V4 = "ipv4";
|
||||
public const string V6 = "ipv6";
|
||||
|
||||
public static bool IsValid(string? value) => value is V4 or V6;
|
||||
|
||||
public static string LineSeries(string probeId, string ipVersion) =>
|
||||
RawChunkHeader.LinePrefix + probeId + (ipVersion == V6 ? ":ipv6" : "");
|
||||
}
|
||||
@@ -58,6 +58,10 @@ public sealed class StreamHeader
|
||||
/// <summary>块头(JSON,自描述):列定义写在块里,新增列或新增 Kind 不需要升级 container_version。</summary>
|
||||
public sealed class RawChunkHeader
|
||||
{
|
||||
[JsonPropertyName("ip_version")]
|
||||
[JsonPropertyOrder(1)]
|
||||
public string IpVersion { get; set; } = IpVersions.V4;
|
||||
|
||||
[JsonPropertyName("chunk_id")]
|
||||
public ChunkId ChunkId { get; set; }
|
||||
|
||||
@@ -113,10 +117,10 @@ public sealed class RawChunkHeader
|
||||
|
||||
/// <summary>
|
||||
/// "line:<probe_id>" 或 "target:<task_id>":存储和分析用的序列标识。
|
||||
/// 一条线路是一对(Probe,Agent):同一个 Agent 上每个 Probe 的数据各是一个序列,互不混合。
|
||||
/// 同一个 Agent 上每个 Probe 的每种地址族各是一个序列,IPv6 追加 :ipv6,互不混合。
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string Series => TaskId is { } id && Target is not null ? "target:" + id.Value : LinePrefix + (ProbeId?.Value ?? "");
|
||||
public string Series => TaskId is { } id && Target is not null ? "target:" + id.Value : IpVersions.LineSeries(ProbeId?.Value ?? "", IpVersion);
|
||||
|
||||
public const string LinePrefix = "line:";
|
||||
}
|
||||
|
||||
@@ -61,6 +61,9 @@ public sealed class TestPhase
|
||||
|
||||
public sealed class TestRunParams
|
||||
{
|
||||
[JsonPropertyName("ip_version")]
|
||||
public string IpVersion { get; set; } = IpVersions.V4;
|
||||
|
||||
[JsonPropertyName("test_id")]
|
||||
public TestId TestId { get; set; }
|
||||
|
||||
@@ -127,6 +130,9 @@ public sealed class AgentEventParams
|
||||
|
||||
public sealed class AgentEndpoint
|
||||
{
|
||||
[JsonPropertyName("ipv6_host")]
|
||||
public string? Ipv6Host { get; set; }
|
||||
|
||||
[JsonPropertyName("agent_id")]
|
||||
public NodeId AgentId { get; set; }
|
||||
|
||||
@@ -289,6 +295,10 @@ public sealed class ProbeHelloMeta
|
||||
/// <summary><c>fleet.hello</c> 的附加字段。</summary>
|
||||
public sealed class AgentHelloMeta
|
||||
{
|
||||
/// <summary>本机是否启用了 IPv6 监听。旧 Agent 缺省为 false,面板不会给它安排 IPv6 会话。</summary>
|
||||
[JsonPropertyName("ipv6_supported")]
|
||||
public bool Ipv6Supported { get; set; }
|
||||
|
||||
[JsonPropertyName("platform")]
|
||||
public PlatformInfo? Platform { get; set; }
|
||||
|
||||
@@ -353,6 +363,9 @@ public sealed class HostSnapshot
|
||||
/// <summary>Agent 眼中的一个已连接 Probe。</summary>
|
||||
public sealed class ConnectedProbe
|
||||
{
|
||||
[JsonPropertyName("ip_version")]
|
||||
public string IpVersion { get; set; } = IpVersions.V4;
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public ProbeId Id { get; set; }
|
||||
|
||||
|
||||
@@ -8,6 +8,21 @@ namespace MoShiro.Protocol.Tests;
|
||||
|
||||
public sealed class RawChunkCodecTests
|
||||
{
|
||||
[Fact]
|
||||
public void Header_LegacyDefaultsToIpv4_AndIpv6RoundTripsToAnIndependentSeries()
|
||||
{
|
||||
RawChunkHeader legacy = System.Text.Json.JsonSerializer.Deserialize("{\"probe_id\":\"prb_legacy\"}", MoShiroJsonContext.Default.RawChunkHeader)!;
|
||||
Assert.Equal(IpVersions.V4, legacy.IpVersion);
|
||||
Assert.Equal("line:prb_legacy", legacy.Series);
|
||||
RawChunk chunk = SampleChunk();
|
||||
chunk.Header.ProbeId = new ProbeId("prb_dual");
|
||||
chunk.Header.IpVersion = IpVersions.V6;
|
||||
RawChunk decoded = RawChunkCodec.Decode(RawChunkCodec.Encode(chunk)).Value;
|
||||
Assert.Equal("ipv6", decoded.Header.IpVersion);
|
||||
Assert.Equal("line:prb_dual:ipv6", decoded.Header.Series);
|
||||
Assert.Equal(chunk.Find("msg")!.Count, decoded.Find("msg")!.Count);
|
||||
}
|
||||
|
||||
private static readonly NodeId s_agent = new("agt_test");
|
||||
|
||||
private static RawChunk SampleChunk()
|
||||
|
||||
Reference in new issue
Block a user