feat(network): add option to disable DSCP tagging (#6067)
Build GH-Pages / prep (push) Successful in 3m30s
Build GH-Pages / call-jekyll-build (push) Failing after 0s

This commit is contained in:
Mikhail authored and GitHub committed 2026-11-08 20:52:56 -05:00
1 parent 7810707f0e
commit 0ddc73d463
9 files changed
+77 -4

No files matched your search

+26
View File
@@ -1914,6 +1914,32 @@ consent prompt for directory ACLs, so the Web UI shows setup steps for correctin
</tr>
</table>
### dscp_tagging
<table>
<tr>
<td>Description</td>
<td colspan="2">
Mark audio and video packets with DSCP priority tags when requested by the client.
@tip{Disabling this may help if audio crackles or stutters on Wi-Fi while the network otherwise appears
healthy. Some routers handle tagged traffic poorly.}
@note{On Windows, disabling this also removes local traffic prioritization.}
</td>
</tr>
<tr>
<td>Default</td>
<td colspan="2">@code{}
enabled
@endcode</td>
</tr>
<tr>
<td>Example</td>
<td colspan="2">@code{}
dscp_tagging = disabled
@endcode</td>
</tr>
</table>
## Config Files
### file_apps
+2
View File
@@ -844,6 +844,7 @@ namespace config {
ENCRYPTION_MODE_NEVER, // lan_encryption_mode
ENCRYPTION_MODE_OPPORTUNISTIC, // wan_encryption_mode
0, // packetsize
true, // dscp_tagging
};
/**
@@ -1811,6 +1812,7 @@ namespace config {
int_between_f(vars, "lan_encryption_mode", stream.lan_encryption_mode, {0, 2});
int_between_f(vars, "wan_encryption_mode", stream.wan_encryption_mode, {0, 2});
int_between_f(vars, "packetsize", stream.packetsize, {0, PACKETSIZE_MAX});
bool_f(vars, "dscp_tagging", stream.dscp_tagging);
path_f(vars, "file_apps", stream.file_apps);
#ifndef __ANDROID__
+2
View File
@@ -272,6 +272,8 @@ namespace config {
// Limit the packetsize to avoid fragmentation on a low MTU link
int packetsize; ///< Maximum payload size for network packets.
bool dscp_tagging; ///< Allow DSCP tagging of audio and video traffic when requested by the client.
};
/**
+2 -2
View File
@@ -2227,7 +2227,7 @@ namespace stream {
// Enable local prioritization and QoS tagging on video traffic if requested by the client
auto address = session->video.peer.address();
session->video.qos = platf::enable_socket_qos(ref->video_sock.native_handle(), address, session->video.peer.port(), platf::qos_data_type_e::video, session->config.videoQosType != 0);
session->video.qos = platf::enable_socket_qos(ref->video_sock.native_handle(), address, session->video.peer.port(), platf::qos_data_type_e::video, config::stream.dscp_tagging && session->config.videoQosType != 0);
BOOST_LOG(debug) << "Start capturing Video"sv;
video::capture(session->mail, session->config.monitor, session);
@@ -2254,7 +2254,7 @@ namespace stream {
// Enable local prioritization and QoS tagging on audio traffic if requested by the client
auto address = session->audio.peer.address();
session->audio.qos = platf::enable_socket_qos(ref->audio_sock.native_handle(), address, session->audio.peer.port(), platf::qos_data_type_e::audio, session->config.audioQosType != 0);
session->audio.qos = platf::enable_socket_qos(ref->audio_sock.native_handle(), address, session->audio.peer.port(), platf::qos_data_type_e::audio, config::stream.dscp_tagging && session->config.audioQosType != 0);
BOOST_LOG(debug) << "Start capturing Audio"sv;
audio::capture(session->mail, session->config.audio, session);
@@ -77,7 +77,8 @@
"lan_encryption_mode": 0,
"wan_encryption_mode": 1,
"ping_timeout": 10000,
"packetsize": 0
"packetsize": 0,
"dscp_tagging": "enabled"
}
},
{
@@ -174,5 +174,13 @@ const effectivePort = computed(() => Number(config.value?.port ?? defaultMoonlig
<div class="form-text">{{ $t('config.packetsize_desc') }}</div>
</div>
<!-- DSCP Tagging -->
<Checkbox class="mb-3"
id="dscp_tagging"
locale-prefix="config"
v-model="config.dscp_tagging"
default="true"
></Checkbox>
</div>
</template>
@@ -241,6 +241,8 @@
"dd_wa_hdr_toggle_delay": "High-contrast workaround for HDR",
"ds4_back_as_touchpad_click": "Map Back/Select to Touchpad Click",
"ds4_back_as_touchpad_click_desc": "When using PlayStation-style gamepad emulation, map Back/Select to Touchpad Click",
"dscp_tagging": "DSCP Tagging",
"dscp_tagging_desc": "Mark audio and video packets with DSCP priority tags when requested by the client. Disabling this may help if audio crackles or stutters on Wi-Fi, as some routers handle tagged traffic poorly.",
"virtualhid_randomize_mac": "Randomize virtual controller MAC",
"virtualhid_randomize_mac_desc": "Use a random MAC address for PlayStation-style virtual controllers instead of one based on the controller index. This avoids mixing per-controller settings when controllers are swapped on the client.",
"encoder": "Force a Specific Encoder",
+15
View File
@@ -220,6 +220,21 @@ TEST_F(ConfigPersistenceTest, ParsesFp16SdrGammaEncodedOption) {
EXPECT_FALSE(config::video.fp16_sdr_gamma_encoded);
}
/**
* @brief Verify the DSCP tagging option parses enabled and disabled values.
*/
TEST_F(ConfigPersistenceTest, ParsesDscpTaggingOption) {
const auto apps_file = config_file().parent_path() / "sunshine_test_config_apps.json";
ASSERT_EQ(file_handler::write_file(apps_file.string().c_str(), "{}"), 0);
config::stream.file_apps = apps_file.string();
config::apply_config_for_test("dscp_tagging = disabled\n");
EXPECT_FALSE(config::stream.dscp_tagging);
config::apply_config_for_test("dscp_tagging = enabled\n");
EXPECT_TRUE(config::stream.dscp_tagging);
}
/**
* @brief Verify mixed-case boolean values update configuration correctly.
*/
+18 -1
View File
@@ -103,7 +103,7 @@ describe('network configuration', () => {
const wrapper = mount(Network, {
props: {
platform: 'linux',
config: { upnp: false },
config: { upnp: false, dscp_tagging: 'enabled' },
},
global: globalOptions,
})
@@ -114,6 +114,23 @@ describe('network configuration', () => {
expect(tableText).toContain('48010')
expect(tableText).not.toContain('NaN')
})
it('toggles DSCP tagging between enabled and disabled', async () => {
const config = { upnp: false, dscp_tagging: 'enabled' }
const wrapper = mount(Network, {
props: { platform: 'linux', config },
global: { ...globalOptions, stubs: { ...globalOptions.stubs, Checkbox: false } },
})
const input = wrapper.get('#dscp_tagging')
expect(input.element.checked).toBe(true)
await input.setValue(false)
expect(config.dscp_tagging).toBe('disabled')
await input.setValue(true)
expect(config.dscp_tagging).toBe('enabled')
})
})
describe('FEC configuration', () => {