MT6000 custom build with LuCi and some optimization - kernel 6.12.x

By "roaming" issue, do you mean that when you roamed from main router WiFi interface to another AP WiFi, that is connected by LAN cable to your main router, you loose connectivity for 5 minutes? If yes, then this patch is meant to work around this issue.

This patch does not do anything to the WED/PPE route.

1 Like

@pesa1234 can you turn on wifi by default in your firmware? I need it on becase I can’t connect the router by cable.

Did you mean that you need a low-cost USB Type-A port or Type-C port <-> ethernet adapter? haha

I do agree. Enabling 2.4Ghz, on channel 6, with 10 character id/password could be a safe bet.

2 Likes

Hi, installed latest build https://github.com/pesa1234/MT6000_cust_build/tree/main/2025-01-26_r29038-a134d8463a_next-r4.5.22.rss.mtk, I forgot how to update software repositaries? should I change some url in openwrt, thanks I'm receiving the following errors: "Collected errors:

OPKG Command APK Equivalent Description

opkg install <pkg>     apk add <pkg>       Install a package
 opkg remove <pkg>      apk del <pkg>       Remove a package
 opkg upgrade           apk upgrade         Upgrade all packages
 opkg files <pkg>       apk info -L <pkg>   List package contents
 opkg list-installed    apk info            List installed packages
 opkg update            apk update          Update package lists
 opkg search <pkg>      apk search <pkg>    Search for packages

For more https://openwrt.org/docs/guide-user/additional-software/opkg-to-apk-che atsheet

2 Likes

should I use this one? "src/gz openwrt_core https://github.com/pesa1234/MT6000_cust_build/raw/main/2025-01-26_r29038-a134d8463a_next-r4.5.22.rss.mtk/targets/mediatek/filogic/packages"

Try fresh install, because it works out of the box

Please explain in more details, Im receiving errors while im doing opkg update command. opkg is not working or it could be fixed somehow my changing custom repo's?

Opkg won't work anymore on my build it is replaced by apk.

so, opkg update command in luci-gui was not replaced by apk? @pesa1234 24.10 released ...

Replaced by apk everywhere on my latest build...

4 Likes

please explain how to use apk from gui? or it is not possible? im newbie in apk...

What happens if you hit update lists in software tab? That what i mean by works out of the box..
No issues using pesa build and installing everything from software without tuning nothing.

resolved, thanks

how do you think is it worth to install stable 24.10 just released few hours ago? or latest build made by pesa1234 is better?

1 Like

Test both and make your choice

4 Likes

A little something I've been cooking up for a few weeks now for ingress auto-rate shaping...

#!/usr/bin/env lua
-- adaptive_sqm.lua
--
-- Adaptive SQM Controller (Lua)
-- Monitors the ifb4eth1 interface for download traffic, applies a PID controller,
-- and updates sqm.eth1.download via UCI. This version imposes:
--   1) a strict max step of 5% from the current rate each update,
--   2) a min rate of 70% of the setpoint,
--   3) outlier detection to reset the PID state, and
--   4) dynamic setpoint updates from UCI.

local posix = require("posix")

-- Register SIGINT handler for graceful termination
local function handle_sigint(signum)
  print("\nSIGINT received, exiting gracefully.")
  os.exit(0)
end
posix.signal(posix.SIGINT, handle_sigint)

-- Helper: run cmd, capture output
local function capture(cmd)
  local f = assert(io.popen(cmd, "r"))
  local s = f:read("*a")
  f:close()
  return s
end

-- Retrieve current SQM download rate (setpoint) from UCI
local function get_setpoint()
  local output = capture("uci get sqm.eth1.download")
  if output then
    local rate = tonumber(output:match("(%d+)"))
    if rate then
      return rate
    end
  end
  error("Failed to retrieve sqm.eth1.download from UCI")
end

-- Script constants
local interface = "ifb4eth1"
local update_interval = 5

-- We'll define variables that can be updated in main loop
local setpoint = get_setpoint()        -- in bps
local min_frac = 0.70                 -- 70% as minimum fraction
local step_frac = 0.05                -- 5% step limit
local outlier_mult = 5.0             -- outlier threshold multiple

local Kp = 0.05
local Ki = 0.005
local Kd = 0.01
local alpha = 0.2

local previous_smoothed = 0
local previous_error = 0
local integral = 0
local current_sqm_rate = setpoint

-- We recalc these dynamically each loop
local min_rate = math.floor(setpoint * min_frac)
local outlier_threshold = math.floor(setpoint * outlier_mult)
local update_threshold = math.floor(0.05 * setpoint)  -- 5% update threshold

-- Sleep using posix.sleep
local function sleep(n) posix.sleep(n) end

-- Wait for interface
local function wait_for_interface(iface, timeout)
  local start_time = os.time()
  while os.difftime(os.time(), start_time) < timeout do
    local file = io.open("/proc/net/dev", "r")
    if file then
      for line in file:lines() do
        if line:match(iface .. ":") then
          file:close()
          return true
        end
      end
      file:close()
    end
    sleep(1)
  end
  return false
end

-- Read rx bytes
local function read_rx_bytes(iface)
  local max_attempts = 5
  for attempt=1,max_attempts do
    local file = io.open("/proc/net/dev", "r")
    if file then
      for line in file:lines() do
        if line:match(iface .. ":") then
          local parts = {}
          for token in line:gmatch("%S+") do
            table.insert(parts, token)
          end
          file:close()
          return tonumber(parts[2])
        end
      end
      file:close()
    end
    print("Interface " .. iface .. " not found, attempt " .. attempt .. " of " .. max_attempts)
    sleep(2)
  end
  error("Interface "..iface.." not found after "..max_attempts.." attempts")
end

-- Hard-limit a new rate to only 5% change from old rate
-- We'll do that after computing new_rate from the PID
local function limit_rate_change(old_rate, raw_new_rate)
  local max_step = old_rate * step_frac   -- 5% of the current rate
  local desired_change = raw_new_rate - old_rate
  
  if desired_change > max_step then
    return old_rate + max_step
  elseif desired_change < -max_step then
    return old_rate - max_step
  else
    return raw_new_rate
  end
end

-- Update SQM
local function update_sqm_rate(new_rate)
  local diff = math.abs(new_rate - current_sqm_rate)
  if diff < update_threshold then
    return
  end
  
  local cmd = string.format("uci set sqm.eth1.download=%d && uci commit sqm && /etc/init.d/sqm restart", math.floor(new_rate))
  print("Running command: "..cmd)
  local res = os.execute(cmd)
  if res ~= 0 then
    print("Error updating SQM rate with command: "..cmd)
  else
    print(string.format("SQM rate updated to %d bps", math.floor(new_rate)))
    sleep(3)
    if not wait_for_interface(interface, 10) then
      io.write("Warning: Interface "..interface.." did not reappear.\n")
    end
  end
  current_sqm_rate = new_rate
end

-- Clear screen
io.write("\27[2J\27[H")
io.write("Adaptive SQM Controller - Press Ctrl-C to exit\n")
io.flush()

local last_bytes = read_rx_bytes(interface)

while true do
  sleep(update_interval)
  
  -- Re-read setpoint from UCI
  local new_setpoint = get_setpoint()
  if new_setpoint ~= setpoint then
    print("\nSetpoint changed from "..setpoint.." bps to "..new_setpoint.." bps.")
    setpoint = new_setpoint
    current_sqm_rate = setpoint
    min_rate = math.floor(setpoint * min_frac)
    outlier_threshold = math.floor(setpoint * outlier_mult)
    update_threshold = math.floor(0.05 * setpoint)
    previous_smoothed = setpoint
    previous_error = 0
    integral = 0
  end

  local new_bytes = read_rx_bytes(interface)
  local diff_bytes = new_bytes - last_bytes
  last_bytes = new_bytes
  local throughput = (diff_bytes * 8)/update_interval
  
  -- Outlier check
  if throughput > outlier_threshold then
    print("\nOutlier detected ("..throughput.." bps). Resetting PID state.")
    previous_smoothed = throughput
    previous_error = 0
    integral = 0
  else
    -- EWMA
    local smoothed = alpha*throughput + (1-alpha)*previous_smoothed
    previous_smoothed = smoothed
    
    -- PID error
    local err = setpoint - smoothed
    
    integral = integral + err*update_interval
    local derivative = (err - previous_error)/update_interval
    
    local correction = Kp*err + Ki*integral + Kd*derivative
    
    local raw_new_rate = current_sqm_rate + correction
    
    -- clamp to [min_rate, setpoint]
    if raw_new_rate < min_rate then raw_new_rate = min_rate end
    if raw_new_rate > setpoint then raw_new_rate = setpoint end
    
    -- limit to 5% step from current_sqm_rate
    local limited_rate = limit_rate_change(current_sqm_rate, raw_new_rate)
    update_sqm_rate(limited_rate)
    
    previous_error = err
    
    io.write(string.format("\rMeasured: %.2f bps | Smoothed: %.2f bps | Err: %.2f | Corr: %.2f | New Rate: %d bps   ",
      throughput, smoothed, err, correction, math.floor(limited_rate)))
    io.flush()
  end
end


Adaptive SQM Controller (Lua)

Overview

This script is designed to help manage your network's download (ingress) rate automatically. It does this by:

  • Monitoring your network: It checks the number of bytes received on the ifb4eth1 interface (which is used for download shaping).
  • Calculating the actual speed: It calculates how fast data is coming in (throughput) in bits per second.
  • Smoothing out fluctuations: It uses a simple method (an Exponential Weighted Moving Average or EWMA) so that temporary spikes or drops don't cause sudden changes.
  • Adjusting the rate with a control loop: It uses a basic PID (Proportional, Integral, Derivative) controller—think of it as a smart dial that nudges your rate up or down to match a target value.
  • Updating SQM settings: When it determines that the download rate should change significantly, it uses OpenWrt’s UCI system to update the SQM (Smart Queue Management) settings and restarts SQM to apply the new rate.
  • Handling interface availability: Since restarting SQM may temporarily remove the ifb4eth1 interface, the script waits until the interface comes back before continuing.
  • Gracefully handling exit: With LuaPosix installed, the script can catch Ctrl‑C (SIGINT) and exit cleanly.
  • Professional output: The script continuously updates a single line on your screen with current status, so you see a live status update without scrolling.

Key Terms (In Plain Language)

  • SQM (Smart Queue Management):
    A system used to manage network traffic so that you get lower latency (less delay) and avoid “bufferbloat” (too much queued data causing slow response times).

  • ifb4eth1:
    A virtual interface used by SQM for shaping incoming (download) traffic. It’s like a temporary holding area for packets before they are passed on.

  • Throughput:
    How much data is passing through your network per second, measured in bits per second (bps).

  • EWMA (Exponential Weighted Moving Average):
    A method of smoothing out quick ups and downs in the measurements to get a more stable number.

  • PID Controller:
    A control system that looks at the difference (error) between what you want (setpoint) and what you’re getting (measured throughput). It then calculates how much to adjust the rate.

    • Proportional (P): Adjusts based on the current error.

    • Integral (I): Looks at past errors to remove any long-term bias.

    • Derivative (D): Predicts future errors based on how quickly the error is changing.

    • (K_p) (Proportional Gain):
      Think of (K_p) like the reaction you have when something is off target right now. Imagine you're trying to keep your video game character at exactly 50 health. If the health is lower than 50, (K_p) tells you how much to immediately add to get back to 50. A higher (K_p) means you react more strongly to the current difference. If it's too high, you might overreact and go past the target.

    • (K_i) (Integral Gain):
      (K_i) is like noticing a slow, steady problem over time. If you’re always a little below 50 health, (K_i) adds up all those small misses and gives you extra correction to fix that long-term issue. It’s like accumulating a debt of “error” that needs to be paid off, so if you’re consistently off, (K_i) helps correct it gradually.

    • (K_d) (Derivative Gain):
      (K_d) looks at how fast things are changing. Imagine you notice that your health is dropping super fast; (K_d) tells you to take action to slow down that drop before you hit a crisis. It predicts what might happen next by looking at the rate of change. If things are changing too quickly, (K_d) helps by “braking” the system—reducing the chance of overshooting the target.

    In short:

    • (K_p) is your immediate reaction to the current error.
    • (K_i) is your adjustment for the accumulated error over time.
    • (K_d) is your anticipation of future error based on how quickly things are changing.

Each one helps balance the control system so it can smoothly hit the target without overreacting or underreacting.

How It Works (Step by Step)

  1. Initialization:

    • The script starts by clearing the screen and displaying a header.
    • It sets a target download rate (setpoint) of 600,000 bits per second (600 Kbps).
    • It also defines a minimum rate (50% of the setpoint) and a threshold (10% of the setpoint) so that small changes won’t trigger a full update.
  2. Monitoring Traffic:

    • Every 5 seconds, the script reads the number of bytes received on the ifb4eth1 interface from the file /proc/net/dev.
    • It calculates how many extra bytes have arrived during those 5 seconds, converts that to bits per second (bps), and treats that as your current throughput.
  3. Smoothing the Data:

    • Because network traffic can have temporary spikes and dips, the script uses EWMA to smooth out the measurements. This gives a more stable “smoothed throughput” value.
  4. Calculating the Error:

    • The script then calculates the error: the difference between your target rate (600 Kbps) and the smoothed throughput.
  5. PID Correction:

    • It uses the PID formula (with three tunable parameters) to calculate how much to adjust your shaping rate.
    • This correction is added to the current SQM rate, but the result is limited so that it never goes above the target rate or below the minimum.
  6. Updating SQM Settings:

    • If the change is significant (more than 10% of the target), the script issues a UCI command to update the SQM download rate (sqm.eth1.download) and restarts SQM.
    • Because SQM restarts take 2–3 seconds and can temporarily remove the ifb4eth1 interface, the script waits until ifb4eth1 reappears before continuing.
  7. Continuous Status Display:

    • Instead of printing a new line every time, the script updates a single status line on your screen. This line shows:
      • The measured throughput (current speed in bps).
      • The smoothed throughput.
      • The error (difference from the target).
      • The correction computed by the PID controller.
      • The new shaping rate.
    • This output updates in place, giving you a live view without the screen scrolling.
  8. Graceful Exit:

    • If you press Ctrl‑C, the script (using LuaPosix) catches the signal and exits cleanly.

How to Use the Script

  1. Install Dependencies:
    • Make sure Lua and LuaPosix are installed on your OpenWrt device.
      opkg update # apk update
      opkg install lua # apk add
      opkg install lua-posix # apk add
      
  2. Copy the Script:
    • Save the script (the file above) as adaptive_sqm.lua on your router.
  3. Make It Executable:
    • Run:
      chmod +x adaptive_sqm.lua
      
  4. Run the Script:
    • Start the script with:
      lua adaptive_sqm.lua
      
    • You will see a status line updating in place.
  5. Exit the Script:
    • Press Ctrl‑C to exit gracefully.

Troubleshooting

  • Interface Not Found:
    If you see messages that ifb4eth1 is not found, it may be due to the SQM restart process. The script is designed to wait until the interface reappears, but if it doesn’t, check your SQM configuration.

  • No SQM Rate Changes:
    If the script keeps reporting “Change (0 bps) below threshold,” it means that the computed adjustments are not large enough to trigger an update. You may need to adjust the PID parameters or the update threshold.

  • Frequent SQM Restarts:
    If SQM is restarting too frequently, consider increasing the update threshold so that only significant changes trigger an update.

Conclusion

This README explains in simple terms what the adaptive SQM Lua script does, how it works, and how to use it. The script monitors your download shaping interface, calculates the current throughput, uses a PID controller to decide if and how to adjust the shaping rate, and then updates SQM accordingly—all while giving you a clear, professional status display and handling Ctrl‑C gracefully.

If you have any further questions or need additional modifications, feel free to ask.


5 Likes

Nice. Could you explain the practical use case of the script? I mean My D/L speed is normally fixed. Is this in case your WAN speed fluctuates a lot? Maybe im missing something

1 Like

@pesa1234 is irqbalance still good to use on latest builds? I see it's not included anymore on your latest builds.

That's exactly what it's intended for.

1 Like