Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
08c8a21
linux bridge works as hub
MinyazevR Nov 1, 2023
295b6d9
Merge pull request #1 from mimi-net/MinyazevR/overlay-fix
MinyazevR Nov 6, 2023
7afe5f0
Mimidump added
MinyazevR Mar 17, 2024
219b03a
Merge pull request #2 from mimi-net/MinyazevR-patch-1
MinyazevR Mar 17, 2024
6382989
Добавил RSTP для switch
ioannessh Mar 2, 2025
70ebd73
Merge pull request #3 from ioannessh/rstp
i1ya Mar 5, 2025
62e27a2
Add stp and rstp priority
ioannessh Mar 15, 2025
d9035f1
Remove vlan filtering
ioannessh Mar 15, 2025
1ce2f9a
Merge pull request #4 from ioannessh/rstp
i1ya Mar 26, 2025
3e1cdcf
Добавил создание конфига и запуск демона
shurenkov Oct 10, 2025
ce758bd
Добавил демон dnsmasq
shurenkov Oct 15, 2025
8b4054d
Merge pull request #5 from ioannessh/dhcp-daemon
i1ya Oct 22, 2025
9c53c96
Убрал устаревший setup.py
shurenkov Nov 8, 2025
064d889
Merge pull request #6 from ioannessh/pyproject_toml
i1ya Nov 8, 2025
e370829
Добавил выбор интерфейсов в Dnsmasq
Nov 21, 2025
238f651
Изменила источник mininet зависимости
vicitori Nov 19, 2025
bb953e8
Merge pull request #7 from ioannessh/dhcp_intf
i1ya Nov 26, 2025
b726055
Update mininet link
vicitori Dec 3, 2025
41e35ce
Update mininet source
vicitori Dec 10, 2025
750b41f
Merge pull request #8 from vicitori/add_duplicate
i1ya Dec 10, 2025
db603e6
First version of dhcp-helper
Apr 12, 2026
5dff299
Garbage commit to check if dnsmasq works as dhcp relay
IgorFilimonov Apr 15, 2026
db07d14
Dnsmasq saga is still going
IgorFilimonov Apr 15, 2026
4cff7aa
Now everything should be okay
IgorFilimonov Apr 15, 2026
75290b9
Merge pull request #9 from IgorFilimonov/master
i1ya Apr 22, 2026
3ac310f
Fix tests and add rootless testing (#11)
iakov Aug 28, 2026
b862e98
fix: faster and more reliable startup for IPv4-only networks (#12)
iakov Aug 28, 2026
f1fb617
perf(tests): speed up the test suite
iakov Aug 29, 2026
74a6bc8
fix(tests): wait for OSPF reconvergence after restoring links
iakov Aug 29, 2026
b6c007c
test: run the suite in parallel via isolated xdist workers
iakov Aug 29, 2026
3801a42
ci: dedupe triggers, cancel stale runs, cache compiled deps
iakov Aug 29, 2026
a2ba863
ci: make the dev container self-sufficient for the full test suite
iakov Aug 29, 2026
363d342
feat(capture): expose capture readiness via wait_until_capturing()
iakov Aug 29, 2026
4ee10a9
fix: restore only missing addresses when bringing an interface back up
iakov Aug 29, 2026
9e10a89
ci: run interface-capture tests in container and bare-metal CI
iakov Aug 29, 2026
db358a1
Bump the actions-dependencies group with 5 updates
dependabot[bot] Aug 30, 2026
cb31c43
fix: bump ExaBGP to 4.2.25 and fix its un-skipped tests
iakov Aug 30, 2026
0fc5b48
build: bump mako to 1.4.1 and migrate docs from m2r to sphinx-mdinclude
iakov Aug 30, 2026
c8691c4
docs: build with uv and add CI job for the documentation
iakov Aug 30, 2026
0e21db0
test: fix flaky exabgp RIB check by polling instead of fixed sleep
iakov Aug 30, 2026
a45b548
test: prevent flaky tests with a shared polling helper
iakov Aug 30, 2026
358c1af
chore: add ruff/mdformat config, pre-commit hooks and CI lint step
iakov Aug 30, 2026
46083b3
style: apply ruff and mdformat auto-fixes
iakov Aug 30, 2026
8f01a88
lint: enable phase-2 rules, convert to py3.12 idioms, defer legacy ru…
iakov Aug 30, 2026
c7fc045
chore: add .git-blame-ignore-revs for the auto-fix reformatting
iakov Aug 30, 2026
0ee53cb
fix: point .git-blame-ignore-revs at the merged auto-fix hash and har…
iakov Aug 30, 2026
28fe656
build: bump project version to 1.2.6
iakov Aug 30, 2026
51d300c
docs: fix stale claims and document project conventions
iakov Aug 30, 2026
ad1fb95
fix(overlay): add strict mode to wait_until_capturing
iakov Aug 31, 2026
6bc82b7
fix(overlay): derive capture header size from magic bytes; accept sta…
iakov Aug 31, 2026
e53dfd8
test(ci): add branch-coverage reporting and a duplicated-code gate
iakov Aug 31, 2026
3c0d746
test: widen the OSPF reconvergence wait for the link-failure suite
iakov Aug 31, 2026
94fbc4e
build: bump project version to 1.2.7
iakov Aug 31, 2026
de0a5ff
test(ci): make the coverage gate tolerant of pre-combined data
iakov Aug 31, 2026
4ee5ef1
test(ci): gate the full-suite branch coverage at the measured baseline
iakov Aug 31, 2026
058d4ea
test(ci): exempt the rootless coverage signal from the full-suite gate
iakov Aug 31, 2026
8421fed
build(container): support Ubuntu 26.04; build PCRE1 from source (#32)
iakov Sep 1, 2026
997618b
ci: pin the Codecov upload slug to the current repository (#33)
iakov Sep 1, 2026
7a04eeb
refactor(install): handle PEP 668 in-code and dedupe distro deps
iakov Sep 1, 2026
ac0627b
chore: remove EOL OpenR daemon support
iakov Sep 1, 2026
6497f55
feat: migrate FRRouting to 10.7.1 with mgmtd-based config (#36)
iakov Sep 2, 2026
3b55203
feat: migrate ExaBGP to 5.0.13 and install it via pip (#37)
iakov Sep 2, 2026
030c659
build(deps): bump the actions-dependencies group across 1 directory w…
dependabot[bot] Sep 3, 2026
ad3713a
ci: run the bare-metal suite on pull requests only (#39)
iakov Sep 3, 2026
55e79f3
test(srv6): wait for IPv6 connectivity before measuring paths (#38)
iakov Sep 3, 2026
2e518a4
test(iptables): poll for the IPv4 ping instead of a single-shot asser…
iakov Sep 3, 2026
13c01c0
ci(coverage): raise full-suite gate to 85 and clear product PLR2004 i…
iakov Sep 4, 2026
ca5cc37
refactor(lint): name all remaining magic comparison constants (#42)
iakov Sep 4, 2026
c308745
test(coverage): cover the dnsmasq, DHCPRelay and IPOVSSwitch modules …
iakov Sep 4, 2026
1ac7cc9
refactor(lint): encode TRY003 messages in exception classes (#44)
iakov Sep 4, 2026
0188094
refactor(lint): split overly-complex helpers and tests (#45)
iakov Sep 4, 2026
04e6f7d
refactor(lint): remove PLR/PLC/TRY003 file-wide ignores (#46)
iakov Sep 4, 2026
2dd70d0
test(coverage): raise the full-suite coverage gate to 90 with scenari…
iakov Sep 5, 2026
cac375b
fix(zebra): always set PrefixListEntry.ge and extend coverage to 92% …
iakov Sep 6, 2026
bc9dca2
test: re-architect the test suite and enforce zero duplicate-code (#49)
iakov Sep 6, 2026
d3ce325
build: prepare v1.3.0 release (#50)
iakov Sep 6, 2026
ccb14ed
fix(bgp): allow explicit route-map ordering of set actions (#51)
iakov Sep 9, 2026
9874fde
build: prepare v1.3.1 release (#52)
iakov Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.git
.venv
.tmp
.pytest_cache
.ruff_cache
.mypy_cache
**/__pycache__
*.pyc
*.log
6 changes: 6 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Revisions to skip in `git blame` — purely mechanical reformatting with no
# semantic change, so blame should attribute the code to its real author.
#
# style: apply ruff and mdformat auto-fixes (ruff lint autofix + ruff
# formatter + mdformat on the markdown files).
46083b313a0aca6d9f1f8ad9e4805044d52c1fef
31 changes: 31 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: 2
updates:
- package-ecosystem: "uv"
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 5
groups:
python-dependencies:
patterns:
- "*"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 5
groups:
actions-dependencies:
patterns:
- "*"

- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 3
groups:
docker-dependencies:
patterns:
- "*"
45 changes: 45 additions & 0 deletions .github/workflows/container-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Containerized CI.
#
# Builds a two-stage image: the builder runs the full install (-a: FRRouting,
# libyang, mininet, radvd, sshd, named) plus the uv venv and mimidump, and the
# slim runtime stage keeps only the test-facing packages and the compiled
# artifacts. Runs the full test suite inside it with root privileges. Every
# worker runs in its own isolated namespace (scripts/run-tests-parallel.sh),
# mirroring the bare-metal job but in a reproducible environment.
#
# Runs on pull requests and on demand; master pushes keep this job too.
name: Container test
on:
pull_request:
push:
branches: [master]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
container-test:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v7
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build and cache test container
uses: docker/build-push-action@v7
with:
file: Containerfile
target: final
push: false
load: true
tags: ipmininet-dev
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run full test suite
run: |
docker run --rm --privileged \
-v $PWD:/workspace:Z \
-e UV_PROJECT_ENVIRONMENT=/opt/venv \
-e DEBIAN_FRONTEND=noninteractive \
ipmininet-dev \
scripts/ci-test.sh
34 changes: 34 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Documentation build.
#
# Builds the Sphinx documentation with the `docs` uv dependency group and
# uploads the resulting HTML as an artifact. The build runs with -W so Sphinx
# warnings fail the job. Runs on every PR and on master; the artifact is
# available from the workflow run page.
name: Build documentation
on:
pull_request:
push:
branches: [master]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
docs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install docs dependencies
run: uv sync --group docs
- name: Build documentation
run: uv run --group docs sphinx-build -b html -W docs docs/_build/html
- name: Upload documentation
uses: actions/upload-artifact@v7
with:
name: ipmininet-docs
path: docs/_build/html
79 changes: 79 additions & 0 deletions .github/workflows/heavy-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Full test suite with coverage, run on master and on demand.
#
# Performs the full `ipmininet.install -a` and runs every test with the
# coverage gate. It complements `test.yaml`, which runs the same suite on pull
# requests: master only changes through merged PRs, so this job is the single
# bare-metal full-suite run per master push and enforces the coverage floor.
# Lint/format checks are run in the `rootless` job of test.yaml.
name: Heavy test
on:
workflow_dispatch:
push:
branches: [master]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
heavy-test:
runs-on: ubuntu-latest
timeout-minutes: 200
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Cache venv
uses: actions/cache@v6
with:
path: .venv
key: venv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
- run: uv sync --all-extras
- name: Record OS version for the deps cache key
run: echo "OS=$(. /etc/os-release && echo $VERSION_ID)" >> "$GITHUB_ENV"
- name: Cache compiled deps
id: cache-deps
uses: actions/cache@v6
with:
path: /home/runner/ci-deps
key: ci-deps-${{ runner.os }}-${{ env.OS }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'ipmininet/install/install.py', 'ipmininet/install/utils.py', 'ipmininet/install/__main__.py') }}
- name: Restore compiled deps
if: steps.cache-deps.outputs.cache-hit == 'true'
run: scripts/ci-restore-deps.sh
- name: Install dependencies (FRRouting, libyang, mininet)
timeout-minutes: 10
run: |
sudo env "PATH=$PATH" uv run python -m ipmininet.install -a
- name: Save compiled deps
if: steps.cache-deps.outputs.cache-hit != 'true'
run: scripts/ci-save-deps.sh
- name: Install mimidump
run: scripts/ci-install-mimidump.sh
- name: Run full test suite (coverage)
timeout-minutes: 170
run: |
sudo env "PATH=$PATH" COVERAGE=1 scripts/run-tests-parallel.sh
- name: Combine and enforce the coverage gate
run: |
sudo env "PATH=$PATH" bash -c '
uv run coverage combine || true
uv run coverage xml -o coverage.xml
uv run coverage html -d htmlcov
uv run coverage report -m
'
- name: Upload coverage report
uses: actions/upload-artifact@v7
with:
name: coverage-full
path: |
coverage.xml
htmlcov/
- name: Upload coverage to Codecov
if: env.CODECOV_TOKEN != ''
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
uses: codecov/codecov-action@v7
with:
files: coverage.xml
flags: full
slug: ${{ github.repository }}
114 changes: 114 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Bare-metal CI, run on pull requests and on demand.
#
# Two jobs:
# - rootless: installs the venv with uv and runs the test suite as the
# default (non-root) runner user. Tests that require root are skipped via
# the `require_root` marker, so this job validates the rootless tests.
# - test: performs the full `ipmininet.install -a` (FRRouting, libyang,
# mininet, ...) and runs the complete test suite with root privileges.
#
# Lint/format checks run in the `rootless` job below, before the light tests.
#
# Runs on pull requests and via manual dispatch (so the full suite can be
# exercised on any branch before merge): master changes arrive through merged
# PRs whose checks already ran here, so re-running this suite on every master
# push would duplicate the coverage-gated `heavy-test.yaml` job. Master pushes
# keep that job plus `container-test.yaml` and `docs.yaml`.
name: Test IPMininet
on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
rootless:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Mininet dependency must be mimi-net fork
run: grep -q 'mimi-net/mininet' pyproject.toml || (echo "mininet dependency must point to mimi-net/mininet.git fork" && exit 1)
- run: uv sync --all-extras
- name: Lint and format checks
run: |
uv run ruff check .
uv run ruff format --check .
uv run mdformat --check README.md LICENSE.md ipmininet/examples/README.md
- name: Check for duplicated code
run: scripts/check-duplicates.sh
- name: Run rootless tests (coverage)
run: |
uv run python -m pytest \
-v \
--cov=ipmininet \
--cov-fail-under=0 \
--cov-report=html:htmlcov \
--cov-report=xml:coverage.xml \
ipmininet/tests/test_pure.py \
ipmininet/tests/test_misc.py \
ipmininet/tests/test_link.py \
ipmininet/tests/test_network_capture.py \
ipmininet/tests/test_bgp_model.py \
ipmininet/tests/test_dhcp.py
- name: Upload coverage report (rootless)
uses: actions/upload-artifact@v7
with:
name: coverage-rootless
path: |
coverage.xml
htmlcov/
- name: Upload coverage to Codecov
if: env.CODECOV_TOKEN != ''
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
uses: codecov/codecov-action@v7
with:
files: coverage.xml
flags: rootless
slug: ${{ github.repository }}
test:
runs-on: ubuntu-latest
timeout-minutes: 200
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Cache venv
uses: actions/cache@v6
with:
path: .venv
key: venv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
- name: Mininet dependency must be mimi-net fork
run: grep -q 'mimi-net/mininet' pyproject.toml || (echo "mininet dependency must point to mimi-net/mininet.git fork" && exit 1)
- run: uv sync --all-extras
- name: Record OS version for the deps cache key
run: echo "OS=$(. /etc/os-release && echo $VERSION_ID)" >> "$GITHUB_ENV"
- name: Cache compiled deps
id: cache-deps
uses: actions/cache@v6
with:
path: /home/runner/ci-deps
key: ci-deps-${{ runner.os }}-${{ env.OS }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'ipmininet/install/install.py', 'ipmininet/install/utils.py', 'ipmininet/install/__main__.py') }}
- name: Restore compiled deps
if: steps.cache-deps.outputs.cache-hit == 'true'
run: scripts/ci-restore-deps.sh
- name: Install dependencies (FRRouting, libyang, mininet)
timeout-minutes: 10
run: |
sudo env "PATH=$PATH" uv run python -m ipmininet.install -a
- name: Save compiled deps
if: steps.cache-deps.outputs.cache-hit != 'true'
run: scripts/ci-save-deps.sh
- name: Install mimidump
run: scripts/ci-install-mimidump.sh
- name: Run test suite
timeout-minutes: 170
run: |
sudo env "PATH=$PATH" scripts/run-tests-parallel.sh
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ tags
*.ropeproject
_build/
docs/api/*.rst
.idea/
.venv/
/.tmp/
.coverage
.coverage.*
coverage.xml
htmlcov/
34 changes: 34 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
default_install_hook_types: [pre-commit, pre-push]
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.5
hooks:
- id: ruff
name: ruff (auto-fix)
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
name: ruff format (auto-format)
- id: ruff
name: ruff (strict check)
stages: [pre-push]
- id: ruff-format
name: ruff format (strict check)
args: [--check]
stages: [pre-push]
- repo: https://github.com/hukkin/mdformat
rev: 1.0.0
hooks:
- id: mdformat
name: mdformat (auto-format)
- id: mdformat
name: mdformat (strict check)
args: [--check]
stages: [pre-push]
- repo: local
hooks:
- id: duplicate-code
name: pylint duplicate-code (zero tolerance)
entry: scripts/check-duplicates.sh
language: system
pass_filenames: false
stages: [pre-push]
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
Loading