{"id":45694053,"url":"https://github.com/galpt/openwrt-bmq","last_synced_at":"2026-02-24T19:02:22.884Z","repository":{"id":340373429,"uuid":"1165747792","full_name":"galpt/openwrt-bmq","owner":"galpt","description":"Adding the BMQ CPU Scheduler to OpenWrt","archived":false,"fork":false,"pushed_at":"2026-02-24T17:56:27.000Z","size":44,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-24T18:52:08.323Z","etag":null,"topics":["cpu-scheduling","linux","linux-kernel","openwrt"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/galpt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-24T13:59:24.000Z","updated_at":"2026-02-24T18:32:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/galpt/openwrt-bmq","commit_stats":null,"previous_names":["galpt/openwrt-bmq"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/galpt/openwrt-bmq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galpt%2Fopenwrt-bmq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galpt%2Fopenwrt-bmq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galpt%2Fopenwrt-bmq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galpt%2Fopenwrt-bmq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/galpt","download_url":"https://codeload.github.com/galpt/openwrt-bmq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/galpt%2Fopenwrt-bmq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29796783,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T16:37:37.581Z","status":"ssl_error","status_checked_at":"2026-02-24T16:37:37.074Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpu-scheduling","linux","linux-kernel","openwrt"],"created_at":"2026-02-24T19:01:45.935Z","updated_at":"2026-02-24T19:02:22.876Z","avatar_url":"https://github.com/galpt.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e 🇺🇸 [English](README.md) · 🇮🇩 [Indonesian](README_ID.md) · 🇨🇳 [Chinese](README_ZH.md) · 🇯🇵 [Japanese](README_JA.md)\n\n# Adding the BMQ CPU Scheduler to OpenWrt\n\nWhat happens when you take OpenWrt — the gold standard of open-source router\nfirmware — and swap its CPU scheduler for something completely different? That\nis exactly what this repository is here to find out.\n\nThis is an experiment. We are replacing the vanilla Linux EEVDF (Earliest Eligible Virtual Deadline First) scheduler inside an OpenWrt x86/64 build with **BMQ (BitMap Queue)**, an\nalternative CPU scheduler authored by Alfred Chen and maintained in the\n[`linux-prjc`](https://gitlab.com/alfredchen/linux-prjc) kernel tree. The whole\nthing is wired up with a GitHub Actions pipeline so every deliberate build\nproduces a ready-to-flash firmware image, no manual intervention required.\n\n---\n\n## Table of Contents\n- [Status](#status)\n- [Why Change the CPU Scheduler?](#why-change-the-cpu-scheduler)\n- [Features](#features)\n- [Requirements](#requirements)\n- [Local Build](#local-build)\n- [CI Pipeline](#ci-pipeline)\n- [Artifact Release](#artifact-release)\n- [Usage](#usage)\n- [Design Notes](#design-notes)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Status\n\n**Current Branch**: `main`\n\n\u003e [!NOTE]\n\u003e This is an active experiment. The CI pipeline targets **OpenWrt v24.10.5** (the latest stable release) with **Linux 6.6.x** on the `x86/64` platform.\n\u003e Builds are triggered manually to keep things deliberate.\n\n## Why Change the CPU Scheduler?\n\nHonest answer first: if you are running OpenWrt on a small embedded router with 128 MB of RAM and a single-core MIPS CPU, you probably do not need this. The default EEVDF (Earliest Eligible Virtual Deadline First) scheduler will serve you just fine.\n\nBut x86 hardware is a different story. When you have a mini PC or a repurposed desktop running OpenWrt, you start doing things that embedded routers were never meant to do — Docker containers, SQM with fq_codel or CAKE for traffic shaping, maybe a few self-hosted services on the side. Suddenly your router is a general-purpose computer that *also* happens to route packets, and the CPU is juggling a very mixed workload.\n\nThis is where an alternative scheduler like BMQ can quietly make a real difference. BMQ (BitMap Queue) was designed to keep latency-sensitive tasks responsive even when the CPU is pegged at 100%. Under heavy load, SQM algorithms like CAKE need to run their packet scheduling logic without getting starved by background tasks. Docker containers need their CPU slices delivered consistently. With the default EEVDF, all of these tasks compete in a way that can introduce jitter under pressure. BMQ handles that competition differently — its bitmap-based priority queuing tends to keep interactive and latency-sensitive workloads snappy even when something else is hammering the CPU in the background.\n\nSo why BMQ specifically and not something newer? Excellent question — there are plenty of interesting schedulers out there. BORE is getting a lot of attention, LAVD looks promising for interactive workloads, and LFBMQ is the direct evolution of BMQ itself. The honest reason we picked BMQ is that this is our *first attempt* at injecting a custom scheduler into an OpenWrt build, and we did not want to be adventurous with something we could not test thoroughly. BMQ has a long track record on the linux-prjc tree, the 6.6 LTS patches are mature and well-maintained, and it felt like the most responsible starting point.\n\nThere is also a hard constraint we cannot work around right now: OpenWrt v24.10.5 still ships with Linux 6.6.x. BORE, LAVD, and LFBMQ all require kernel 6.10 or newer to apply cleanly. Until OpenWrt bumps its kernel version, those options are simply out of reach. BMQ on 6.6 is what we have — and for the use case described above, it is a perfectly reasonable thing to experiment with.\n\n## Features\n\n- Pins to **OpenWrt v24.10.5** — no surprises from rolling upstream changes.\n- Uses `CONFIG_KERNEL_GIT_CLONE_URI` to pull the kernel directly from the\n  `linux-6.6.y-prjc-lts` branch of `linux-prjc` — the official OpenWrt\n  mechanism for custom kernels, no tarball hacks needed.\n- Enables BMQ via a kernel config fragment appended to\n  `target/linux/x86/config-6.6` (`CONFIG_SCHED_ALT=y` + `CONFIG_SCHED_BMQ=y`).\n- Supports dropping extra `*.patch` files into `bmq-patches/` for ad-hoc\n  kernel customisation without touching the workflow.\n- Produces `squashfs` and `ext4` combined images (both BIOS and EFI variants)\n  as `.img.gz` artifacts.\n- Publishes every successful build to GitHub Releases with a `SHA256SUMS.txt`.\n- Build log is always uploaded as an artifact — even on failure — so there is\n  something to look at when things go wrong.\n\n## Requirements\n\nYou will need a Debian/Ubuntu machine with the standard OpenWrt build\ndependencies installed:\n\n```bash\nsudo apt-get update\nsudo apt-get install -y --no-install-recommends \\\n  build-essential ccache clang flex bison g++ gawk \\\n  gcc-multilib g++-multilib gettext git libfuse-dev \\\n  libncurses5-dev libssl-dev python3-setuptools \\\n  rsync subversion swig unzip util-linux wget \\\n  xsltproc zlib1g-dev file python3 python3-pip \\\n  squashfs-tools xz-utils quilt\n```\n\nOther distributions should provide equivalent packages. The CI runner uses\n`ubuntu-latest`.\n\n## Local Build\n\nThe steps below mirror exactly what the CI pipeline does. If it builds\nlocally, it will build in CI.\n\n1. **Clone this repository**\n   ```bash\n   git clone https://github.com/galpt/openwrt-bmq.git\n   cd openwrt-bmq\n   ```\n\n2. **Clone OpenWrt v24.10.5**\n   ```bash\n   git clone --depth 1 --branch v24.10.5 \\\n     https://github.com/openwrt/openwrt.git openwrt\n   ```\n\n3. **Install feeds**\n   ```bash\n   cd openwrt\n   ./scripts/feeds update -a\n   ./scripts/feeds install -a\n   ```\n\n4. **Write the build config**\n\n   The key here is `CONFIG_KERNEL_GIT_CLONE_URI`. When this is set, OpenWrt\n   clones the kernel from the given git URL instead of downloading its own\n   tarball, and the hash check is bypassed automatically.\n\n   ```bash\n   # inside the openwrt/ directory\n   printf '%s\\n' \\\n     'CONFIG_TARGET_x86=y' \\\n     'CONFIG_TARGET_x86_64=y' \\\n     'CONFIG_TARGET_MULTI_PROFILE=y' \\\n     'CONFIG_TARGET_DEVICE_x86_64_DEVICE_generic=y' \\\n     'CONFIG_KERNEL_GIT_CLONE_URI=\"https://gitlab.com/alfredchen/linux-prjc.git\"' \\\n     'CONFIG_KERNEL_GIT_REF=\"linux-6.6.y-prjc-lts\"' \\\n     \u003e .config\n\n   make defconfig\n\n   # Append BMQ scheduler options to the x86 kernel config fragment\n   printf '\\n# BMQ (BitMap Queue) CPU Scheduler\\nCONFIG_SCHED_ALT=y\\nCONFIG_SCHED_BMQ=y\\n# CONFIG_SCHED_PDS is not set\\n' \\\n     \u003e\u003e target/linux/x86/config-6.6\n   ```\n\n5. **Add optional patches** (skip if you have none):\n   Place any `*.patch` files under `bmq-patches/` at the root of this repo.\n   They get copied into `openwrt/target/linux/x86/patches-6.6/` automatically.\n\n6. **Build**\n   ```bash\n   # inside openwrt/\n   make -j$(nproc) V=s\n   # fall back if the parallel build races\n   make -j1 V=s\n   ```\n\n7. **Collect the images**\n   ```bash\n   mkdir -p ../dist\n   cp bin/targets/x86/64/*squashfs-combined*.img.gz ../dist/\n   cp bin/targets/x86/64/*ext4-combined*.img.gz     ../dist/\n   ls -lh ../dist\n   ```\n\n\u003e [!TIP]\n\u003e OpenWrt compresses all output images with gzip. The files you are looking for are `*.img.gz`, not bare `*.img`.\n\n## CI Pipeline\n\nThe workflow lives in `.github/workflows/build-and-release.yml` and is\n**manually triggered only** (`workflow_dispatch`). We made this choice\ndeliberately — every build is a conscious decision, not an automatic reaction\nto a commit.\n\nHere is the high-level sequence:\n\n1. Install build dependencies on a fresh `ubuntu-latest` runner.\n2. Clone OpenWrt v24.10.5.\n3. Update and install all feeds.\n4. Write `.config` with `CONFIG_KERNEL_GIT_CLONE_URI` pointing to `linux-prjc`,\n   run `make defconfig`, and append the BMQ Kconfig options.\n5. Copy any patches from `bmq-patches/` if present.\n6. Run `make -j$(nproc) V=s`, falling back to `-j1` on failure.\n7. Collect `*squashfs-combined*.img.gz` and `*ext4-combined*.img.gz` from the\n   output directory.\n8. Pass the images to the `create-release` job which publishes them as a\n   timestamped GitHub Release.\n\nThe build log is always uploaded as an artifact — even when the build fails —\nso there is always something to read when debugging.\n\n\u003e [!NOTE]\n\u003e The release tag is derived from the Git ref if you push a tag, or auto-generated as `openwrt-bmq-YYYYMMDD-HHmmss` when triggered manually against a branch.\n\n## Artifact Release\n\nEvery successful run publishes a GitHub Release containing:\n\n| File | Boot | Root filesystem |\n|------|------|-----------------|\n| `*squashfs-combined.img.gz`     | Legacy BIOS | squashfs — read-only |\n| `*squashfs-combined-efi.img.gz` | UEFI        | squashfs — read-only |\n| `*ext4-combined.img.gz`         | Legacy BIOS | ext4 — writable      |\n| `*ext4-combined-efi.img.gz`     | UEFI        | ext4 — writable      |\n| `SHA256SUMS.txt`                | —           | checksums for all of the above |\n\nThe squashfs variants are the recommended choice for most use cases — they are\nsmaller, read-only by design, and behave exactly like a typical OpenWrt flash\nimage.\n\n## Usage\n\nOnce you have grabbed an image from the Releases page, here is how to put it\nto use:\n\n```bash\n# Decompress\ngunzip openwrt-*-squashfs-combined.img.gz\n\n# Write to a USB stick or disk — replace /dev/sdX carefully\ndd if=openwrt-*-squashfs-combined.img of=/dev/sdX bs=4M status=progress\nsync\n\n# Or skip the hardware and test immediately with QEMU\nqemu-system-x86_64 \\\n  -drive file=openwrt-*-squashfs-combined.img,format=raw \\\n  -m 256m -nographic\n```\n\nOnce it boots you land in a standard OpenWrt shell. Package management,\nnetwork configuration, and everything else works the same as upstream — the\nonly difference is the CPU scheduler running underneath.\n\n```bash\n# Verify BMQ is active after booting\ncat /sys/kernel/debug/sched/features\n# or check dmesg for scheduler init messages\ndmesg | grep -i sched\n```\n\n## Design Notes\n\n- **Why `CONFIG_KERNEL_GIT_CLONE_URI` and not a tarball?** OpenWrt verifies\n  the SHA256 of every kernel tarball it downloads. Renaming a custom tarball\n  to match the expected filename does not fool the hash check — the build\n  silently downloads the real kernel anyway and BMQ never gets compiled in.\n  `CONFIG_KERNEL_GIT_CLONE_URI` is the mechanism OpenWrt officially supports\n  for this exact use case, and it disables the hash check by design.\n\n- **Why Linux 6.6?** The `linux-prjc` BMQ patches are maintained for the\n  6.6 LTS kernel family (`linux-6.6.y-prjc-lts`). OpenWrt v24.10.5 targets\n  `KERNEL_PATCHVER=6.6` for x86, which makes them a natural fit. Newer kernel\n  versions do not yet have an actively maintained BMQ port.\n\n- **Why x86/64?** It is the easiest platform to test — you can spin up a QEMU\n  VM in seconds without needing physical hardware. The same approach could, in\n  theory, be adapted for other architectures if the scheduler patches are\n  compatible.\n\n- **The `bmq-patches/` directory** is intentionally left empty in the\n  repository. Drop your own `*.patch` files there if you want to layer\n  additional changes on top of `linux-prjc` without modifying the workflow.\n\n- **Apt mirror selection** is done before `apt-get update` runs. The pipeline\n  probes `archive.ubuntu.com`, `azure.archive.ubuntu.com`, and\n  `us.archive.ubuntu.com` with a 3-second `curl` timing check and rewrites\n  the apt sources to point at whichever responds fastest. A short per-connection\n  timeout (10 s) and 5 retries are also configured so a flaky host is abandoned\n  quickly instead of hanging the job for minutes.\n\n- **Build timeouts** in CI are set to 5 hours. A cold build with kernel\n  compilation can take a long time on a shared GitHub runner.\n\n## Contributing\n\nThis is an experiment and contributions are very welcome — patches, ideas,\nbug reports, all of it.\n\n1. Fork the repository and create a feature branch.\n2. If you are adding kernel patches, place them in `bmq-patches/` and verify\n   they apply cleanly against `linux-6.6.y-prjc-lts`.\n3. If you are changing the workflow, test it with `workflow_dispatch` before\n   opening a pull request.\n4. Open the pull request and describe what you changed and why.\n\n\u003e [!NOTE]\n\u003e Please do not add triggers that auto-run the workflow on every push. Builds are expensive and we want them to be intentional.\n\n## License\n\nThis project is provided under the **MIT License**. See the [LICENSE](LICENSE)\nfile for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgalpt%2Fopenwrt-bmq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgalpt%2Fopenwrt-bmq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgalpt%2Fopenwrt-bmq/lists"}