Skip to content

Commit 02b3b35

Browse files
committed
Fix WAN Steering not discovering VLAN-tagged and GRE interfaces (#566)
ParseIpRules regex only matched eth\d+ and ppp\d+, silently dropping VLAN-tagged WANs (eth6.228) and GRE tunnels (gre1) from LTE/5G modems. Broadened to match any Linux interface name with optional VLAN suffix.
1 parent 93030e9 commit 02b3b35

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

src/NetworkOptimizer.Web/Services/WanSteerDeploymentService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ internal static string SanitizeWanKey(string name)
499499
internal static Dictionary<string, (string FWMark, string RouteTable)> ParseIpRules(string output)
500500
{
501501
var map = new Dictionary<string, (string FWMark, string RouteTable)>();
502-
var regex = new Regex(@"fwmark\s+(0x[0-9a-f]+)/0x7e0000\s+lookup\s+(\d+\.(eth\d+|ppp\d+))");
502+
var regex = new Regex(@"fwmark\s+(0x[0-9a-f]+)/0x7e0000\s+lookup\s+(\d+\.([a-z][a-z0-9]*(?:\.\d+)?))");
503503

504504
foreach (var line in output.Split('\n'))
505505
{

tests/NetworkOptimizer.Web.Tests/WanSteerDeploymentServiceTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,51 @@ public void Returns_empty_for_empty_output()
6969
WanSteerDeploymentService.ParseIpRules("").Should().BeEmpty();
7070
}
7171

72+
[Fact]
73+
public void Parses_vlan_tagged_interface()
74+
{
75+
var output = "32508: from all fwmark 0x1a0000/0x7e0000 lookup 201.eth6.228\n";
76+
77+
var result = WanSteerDeploymentService.ParseIpRules(output);
78+
79+
result.Should().ContainKey("eth6.228");
80+
result["eth6.228"].FWMark.Should().Be("0x1a0000");
81+
result["eth6.228"].RouteTable.Should().Be("201.eth6.228");
82+
}
83+
84+
[Fact]
85+
public void Parses_gre_interface()
86+
{
87+
var output = "32510: from all fwmark 0x6e0000/0x7e0000 lookup 180.gre1\n";
88+
89+
var result = WanSteerDeploymentService.ParseIpRules(output);
90+
91+
result.Should().ContainKey("gre1");
92+
result["gre1"].FWMark.Should().Be("0x6e0000");
93+
result["gre1"].RouteTable.Should().Be("180.gre1");
94+
}
95+
96+
[Fact]
97+
public void Parses_real_gateway_output_with_mixed_interfaces()
98+
{
99+
var output = string.Join("\n",
100+
"0: from all lookup local",
101+
"32504: from all fwmark 0x1c0000/0x7e0000 lookup 202.eth0",
102+
"32506: from all fwmark 0x720000/0x7e0000 lookup 182.eth1",
103+
"32508: from all fwmark 0x1a0000/0x7e0000 lookup 201.eth6.228",
104+
"32510: from all fwmark 0x6e0000/0x7e0000 lookup 180.gre1",
105+
"32766: from all lookup main",
106+
"32767: from all lookup default");
107+
108+
var result = WanSteerDeploymentService.ParseIpRules(output);
109+
110+
result.Should().HaveCount(4);
111+
result.Should().ContainKey("eth0");
112+
result.Should().ContainKey("eth1");
113+
result.Should().ContainKey("eth6.228");
114+
result.Should().ContainKey("gre1");
115+
}
116+
72117
[Fact]
73118
public void Ignores_non_matching_fwmark_masks()
74119
{

0 commit comments

Comments
 (0)