Browse Source

fixes in TC default class logic

pull/2684/head
pavelrzn 1 week ago
parent
commit
6cc5470202
  1. 25
      src/app/pages/admin/speed.vue
  2. 6
      src/i18n/locales/en.json
  3. 6
      src/i18n/locales/ru.json
  4. 7
      src/server/utils/TCManager.ts

25
src/app/pages/admin/speed.vue

@ -45,15 +45,12 @@
</label>
<div class="flex items-center gap-3">
<input
v-model.number="data.tcState.defaultClassId"
v-model.number="defaultClassSpeed"
type="number"
min="1"
max="255"
class="w-32 rounded-lg border-2 border-gray-100 text-gray-500 focus:border-red-800 focus:outline-0 focus:ring-0 dark:border-neutral-800 dark:bg-neutral-700 dark:text-neutral-200 dark:placeholder:text-neutral-400"
>
<span class="text-xs text-gray-400 dark:text-neutral-500">
{{ $t('admin.speed.defaultClassIdDesc') }}
</span>
</div>
</div>
</div>
@ -226,6 +223,21 @@ function getClientsForClass(cls: TcClass): TcClient[] {
return data.value.clients.filter((c) => c.ipv4Address && ipSet.has(c.ipv4Address));
}
// Default class speed (without '2' prefix)
const defaultClassSpeed = computed({
get: () => {
if (!data.value) return 0;
const s = String(data.value.tcState.defaultClassId);
// Strip leading '2' if present
return s.startsWith('2') ? parseInt(s.slice(1), 10) || 0 : data.value.tcState.defaultClassId;
},
set: (val: number) => {
if (data.value) {
data.value.tcState.defaultClassId = val;
}
},
});
// Drag state
const dragState = ref<{ client: TcClient; fromClassIdx: number | null } | null>(null);
@ -318,7 +330,10 @@ async function applyConfig() {
try {
const res = await $fetch('/api/tc/state', {
method: 'post',
body: data.value.tcState,
body: {
...data.value.tcState,
defaultClassId: parseInt('2' + String(defaultClassSpeed.value), 10),
},
});
if (res.success) {

6
src/i18n/locales/en.json

@ -164,9 +164,9 @@
"apply": "Apply Configuration",
"totalBandwidth": "Total Bandwidth (UL rate)",
"totalBandwidthDesc": "Root class 1:1 — max bandwidth",
"defaultClassId": "Default Class ID",
"defaultClassIdDesc": "Unmatched traffic goes to this class",
"unassigned": "Unassigned Clients",
"defaultClassId": "Default Class",
"defaultClassIdDesc": "",
"unassigned": "Default Class",
"noUnassigned": "All clients are assigned",
"classLabel": "Class",
"removeClass": "Remove class",

6
src/i18n/locales/ru.json

@ -155,9 +155,9 @@
"apply": "Применить конфигурацию",
"totalBandwidth": "Общая пропускная способность (UL rate)",
"totalBandwidthDesc": "Root class 1:1 — максимальная пропускная способность",
"defaultClassId": "ID класса по умолчанию",
"defaultClassIdDesc": "Несопоставленный трафик идёт в этот класс",
"unassigned": "Клиенты без класса",
"defaultClassId": "Класс по умолчанию",
"defaultClassIdDesc": "",
"unassigned": "Класс по умолчанию",
"noUnassigned": "Все клиенты распределены",
"classLabel": "Класс",
"removeClass": "Удалить класс",

7
src/server/utils/TCManager.ts

@ -75,7 +75,7 @@ class TCManager {
}
// Step 2: Create root qdisc with default class
TC_DEBUG(`Creating root qdisc (default ${state.defaultClassId})...`);
TC_DEBUG(`Creating root qdisc (default ${state.defaultClassId}) with ${String(state.defaultClassId).slice(1)}Mbit...`);
try {
await execAsync(
`tc qdisc add dev ${this.device} parent root handle 1: hfsc default ${state.defaultClassId}`,
@ -93,6 +93,11 @@ class TCManager {
`tc class add dev ${this.device} parent 1: classid 1:1 hfsc sc rate ${totalUlRate}mbit ul rate ${totalUlRate}mbit`,
{ timeout: 10000 }
);
const ul: string = String(state.defaultClassId).slice(1);
await execAsync(
`tc class add dev ${this.device} parent 1:1 classid 1:${state.defaultClassId} hfsc ls rate ${ul}mbit ul rate ${ul}mbit`,
{ timeout: 10000 }
);
} catch (err: any) {
const errMsg = (err?.stderr || err?.message || '').toLowerCase();
if (!errMsg.includes('exists')) {

Loading…
Cancel
Save