├── .github ├── ISSUE_TEMPLATE │ ├── question.md │ ├── feature_request.md │ └── bug_report.md ├── dependabot.yml ├── workflows │ ├── changelog.yml │ ├── publish.yml │ ├── cargo-lint.yml │ └── cargo-test.yml └── PULL_REQUEST_TEMPLATE.md ├── src ├── lib.rs ├── error.rs ├── core.rs └── executor.rs ├── examples ├── README.md └── simple.rs ├── config.toml ├── .gitignore ├── config.ron ├── Cargo.toml ├── assets └── simple-ns3.cc ├── setup-ns3.sh ├── CHANGELOG.md ├── README.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── LICENSE /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question about this project 4 | title: "[question]" 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod core; 2 | pub mod error; 3 | pub mod executor; 4 | 5 | pub use crate::core::{BuildCmd, BuildParam}; 6 | pub use crate::executor::{Executor, ExecutorBuilder}; 7 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Do remember to run the script `setup-ns3.sh` first to execute the example. 4 | 5 | The script will download ns3 for you and then copy the example scratch from `assets` to the scratch folder of ns-3. 6 | 7 | For more details please see the script. 8 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | [exp-1] 2 | policy = [1, 2] 3 | app_name = "ns3-tcp-bbr" 4 | sim_time = 5 5 | 6 | [exp-2] 7 | policy = [1, 2, 3, 4] 8 | app_name = "ns3-tcp-cubic" 9 | sim_time = 2 10 | 11 | [exp-3] 12 | policy = [1, 2, 3, 4] 13 | app_name = "ns3-tcp-copa" 14 | 15 | [exp-4] 16 | app_name = "ns3-tcp-creno" 17 | sim_time = 2 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # NS-3 13 | ns-allinone-* -------------------------------------------------------------------------------- /config.ron: -------------------------------------------------------------------------------- 1 | { 2 | "exp-1": ( 3 | policy: [ 4 | 1, 2 5 | ], 6 | app_name: "ns3-tcp-bbr", 7 | sim_time: 5, 8 | ), 9 | "exp-2": ( 10 | policy: [ 11 | 1, 2, 3, 4 12 | ], 13 | app_name: "ns3-tcp-cubic", 14 | sim_time: 2, 15 | ), 16 | "exp-3": ( 17 | policy: [ 18 | 1, 2, 3, 4 19 | ], 20 | app_name: "ns3-tcp-copa", 21 | ), 22 | "exp-4": ( 23 | app_name: "ns3-tcp-creno", 24 | sim_time: 2, 25 | ) 26 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "cargo" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | reviewers: 11 | - BobAnkh 12 | schedule: 13 | interval: "daily" 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[enhancement]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Is your feature request related to a problem? Please describe 11 | 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when \[...] 13 | 14 | ## Description of the new feature/enhancement 15 | 16 | A clear and concise description of what you want to happen. 17 | 18 | ## Proposed technical implementation details (optional) 19 | 20 | A clear and concise description of any solutions you've considered. 21 | 22 | ## Additional context 23 | 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ns3-parallel" 3 | version = "0.2.3" 4 | edition = "2021" 5 | license = "Apache-2.0" 6 | description = "A Multitask Parallel Concurrent Executor for ns-3 (network simulator)." 7 | readme = "README.md" 8 | homepage = "https://github.com/BobAnkh/ns3-parallel" 9 | repository = "https://github.com/BobAnkh/ns3-parallel" 10 | keywords = ["multitask", "parallel", "ns3", "network", "simulation"] 11 | documentation = "https://docs.rs/ns3-parallel" 12 | categories = ["concurrency", "network-programming", "simulation"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | toml = "0.9.0" 18 | tokio = { version = "1.46.1", features = ["full"] } 19 | serde = { version = "1.0", features = ["derive"] } 20 | futures = "0.3" 21 | pbr = "1.0.4" 22 | num_cpus = "1.13" 23 | ron = "0.12" 24 | serde_json = "1.0" 25 | serde_yaml = "0.9" 26 | -------------------------------------------------------------------------------- /assets/simple-ns3.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | #include "ns3/core-module.h" 3 | 4 | using namespace ns3; 5 | 6 | NS_LOG_COMPONENT_DEFINE("SimpleSimulator"); 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | NS_LOG_UNCOND("A Simple NS3 Example of ns3-parallel"); 11 | std::string app_name; 12 | 13 | uint32_t sim_time = 10; 14 | uint32_t policy = 0; 15 | 16 | /* Command line arguments */ 17 | CommandLine cmd(__FILE__); 18 | cmd.AddValue("app-name", "The name of apps", app_name); 19 | cmd.AddValue("sim-time", "Total duration of the simulation (in s). Default to 10", sim_time); 20 | cmd.AddValue("policy", "Policy of program", policy); 21 | cmd.Parse(argc, argv); 22 | 23 | NS_LOG_UNCOND("[Param] app_name: " << app_name << " policy: " << policy << " sim_time: " << sim_time); 24 | Simulator::Stop(Seconds(sim_time + 1)); 25 | Simulator::Run(); 26 | Simulator::Destroy(); 27 | } 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[bug]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | 12 | A clear and concise description of what the bug is. 13 | 14 | ## To Reproduce 15 | 16 | > **NOTE**:Self-contained, minimal reproducing samples are extremely helpful and will expedite addressing your issue 17 | 18 | Steps to reproduce the behavior: 19 | 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. Scroll down to '....' 23 | 4. See error 24 | 25 | ## Expected behavior 26 | 27 | A clear and concise description of what you expected to happen. 28 | 29 | ## Screenshots 30 | 31 | If applicable, add screenshots to help explain your problem. 32 | 33 | ## Environment 34 | 35 | 36 | - Device: \[e.g. iPhone6] 37 | - OS: \[e.g. Ubuntu 18.04LTS] 38 | - Browser \[e.g. chrome, safari] 39 | - Version \[e.g. 22] 40 | 41 | ## Additional context 42 | 43 | Add any other context about the problem here. 44 | -------------------------------------------------------------------------------- /setup-ns3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### 3 | # @Author : BobAnkh 4 | # @Github : https://github.com/BobAnkh 5 | # @Date : 2022-01-23 02:28:04 6 | # @LastEditors : BobAnkh 7 | # @LastEditTime : 2022-01-23 09:04:06 8 | # @Description : 9 | # Copyright 2022 BobAnkh 10 | ### 11 | 12 | current_dir=$(pwd) 13 | 14 | # ns3 version 3.33 15 | ns3_ver="3.33" 16 | ns3_folder="ns-allinone-${ns3_ver}" 17 | ns3_scratch="${current_dir}/${ns3_folder}/ns-${ns3_ver}/scratch" 18 | 19 | # download ns3 to current dir 20 | if [ ! -d "${current_dir}"/${ns3_folder} ]; then 21 | ns3_file_name="ns-allinone-${ns3_ver}.tar.bz2" 22 | url="https://www.nsnam.org/releases/${ns3_file_name}" 23 | if [ ! -f "${current_dir}/${ns3_file_name}" ]; then 24 | echo "Downloading NS3-${ns3_ver}..." 25 | wget --show-progress --quiet $url 26 | fi 27 | # unzip 28 | echo "Unzipping ${ns3_file_name}..." 29 | tar xjf ${ns3_file_name} 30 | fi 31 | 32 | # compile (opitonal) 33 | echo "Compiling ns3..." 34 | cd "${current_dir}"/${ns3_folder} || return 35 | ./build.py 36 | 37 | # link scratch in assets 38 | echo "Copying example scratch to ns3..." 39 | ln -s -v "${current_dir}"/assets/*.cc "${ns3_scratch}"/ 40 | -------------------------------------------------------------------------------- /.github/workflows/changelog.yml: -------------------------------------------------------------------------------- 1 | name: Generate changelog 2 | on: 3 | release: 4 | types: [created, edited] 5 | push: 6 | branches: 7 | - main 8 | workflow_dispatch: 9 | 10 | jobs: 11 | generate-changelog: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 0 17 | - uses: BobAnkh/auto-generate-changelog@master 18 | with: 19 | ACCESS_TOKEN: ${{secrets.GITHUB_TOKEN}} 20 | PATH: 'CHANGELOG.md' 21 | COMMIT_MESSAGE: 'docs(changelog): update release notes' 22 | TYPE: 'feat:Feature,fix:Bug Fixes,docs:Documentation,refactor:Refactor,perf:Performance Improvements' 23 | 24 | add-contributors: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v2 28 | - uses: BobAnkh/add-contributors@master 29 | with: 30 | CONTRIBUTOR: '### Contributors' 31 | COLUMN_PER_ROW: '6' 32 | ACCESS_TOKEN: ${{secrets.GITHUB_TOKEN}} 33 | IMG_WIDTH: '100' 34 | FONT_SIZE: '14' 35 | PATH: 'README.md' 36 | COMMIT_MESSAGE: 'docs(readme): update contributors' 37 | AVATAR_SHAPE: 'round' 38 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Crates.io 2 | 3 | # Controls when the action will run. Workflow runs when manually triggered using the UI 4 | # or API. 5 | on: 6 | release: 7 | types: [created] 8 | workflow_dispatch: 9 | # Inputs the workflow accepts. 10 | inputs: 11 | name: 12 | # Friendly description to be shown in the UI instead of 'name' 13 | description: 'Publish crate' 14 | # Default value if no value is explicitly provided 15 | default: 'ns3-parallel' 16 | # Input has to be provided for the workflow to run 17 | required: false 18 | 19 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 20 | jobs: 21 | publish: 22 | # The type of runner that the job will run on 23 | runs-on: ubuntu-latest 24 | 25 | # Steps represent a sequence of tasks that will be executed as part of the job 26 | steps: 27 | - uses: actions/checkout@v2 28 | - uses: actions-rs/toolchain@v1 29 | with: 30 | toolchain: stable 31 | override: true 32 | - uses: katyo/publish-crates@v1 33 | with: 34 | registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} 35 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | //! Error 2 | 3 | use ron::error::SpannedError; 4 | use std::io; 5 | use tokio::task::JoinError; 6 | 7 | /// # Error 8 | /// 9 | /// Error type for NS3 executor. 10 | #[derive(Debug, Clone)] 11 | pub enum Error { 12 | InvalidConfig(String), 13 | FileNotFound(String), 14 | InvalidConfigFormat(String), 15 | ExecuteFail(String), 16 | BuildFail(String), 17 | IoError(String), 18 | JoinError(String), 19 | NotImplement(String), 20 | RetryLimitExceed, 21 | } 22 | 23 | impl From for Error { 24 | fn from(e: io::Error) -> Self { 25 | Error::IoError(format!("{e:?}")) 26 | } 27 | } 28 | 29 | impl From for Error { 30 | fn from(e: JoinError) -> Self { 31 | Error::JoinError(format!("{e:?}")) 32 | } 33 | } 34 | 35 | impl From for Error { 36 | fn from(e: SpannedError) -> Self { 37 | Error::InvalidConfigFormat(format!("{e:?}")) 38 | } 39 | } 40 | 41 | impl From for Error { 42 | fn from(e: serde_json::Error) -> Self { 43 | Error::InvalidConfigFormat(format!("{e:?}")) 44 | } 45 | } 46 | 47 | impl From for Error { 48 | fn from(e: serde_yaml::Error) -> Self { 49 | Error::InvalidConfigFormat(format!("{e:?}")) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/cargo-lint.yml: -------------------------------------------------------------------------------- 1 | name: Cargo Lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | pull_request: 9 | types: [ready_for_review, opened, synchronize, reopened] 10 | paths: 11 | - '**.rs' 12 | - '**/Cargo.toml' 13 | workflow_dispatch: 14 | 15 | jobs: 16 | cargo-check: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v2 22 | 23 | - name: Install latest stable 24 | uses: dtolnay/rust-toolchain@stable 25 | with: 26 | toolchain: stable 27 | 28 | - name: deal with rust cache 29 | uses: Swatinem/rust-cache@v1 30 | 31 | - name: cargo check 32 | run: cargo check --all-targets --all-features --workspace 33 | 34 | cargo-build: 35 | runs-on: ubuntu-latest 36 | 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v2 40 | 41 | - name: Install latest stable 42 | uses: dtolnay/rust-toolchain@stable 43 | with: 44 | toolchain: stable 45 | 46 | - name: deal with rust cache 47 | uses: Swatinem/rust-cache@v1 48 | 49 | - name: cargo build 50 | run: cargo build --all-features 51 | 52 | cargo-clippy: 53 | runs-on: ubuntu-latest 54 | 55 | steps: 56 | - name: Checkout 57 | uses: actions/checkout@v2 58 | 59 | - name: Install latest stable 60 | uses: dtolnay/rust-toolchain@stable 61 | with: 62 | toolchain: stable 63 | components: clippy 64 | 65 | - name: deal with rust cache 66 | uses: Swatinem/rust-cache@v1 67 | - run: cargo clippy --workspace --all-features --tests -- -Dwarnings 68 | 69 | # temporarily change to a self-maintained workflow 70 | # see https://github.com/actions-rs/clippy-check/pull/158 71 | # - name: cargo clippy 72 | # uses: BobAnkh/clippy-check@master 73 | # with: 74 | # token: ${{ secrets.GITHUB_TOKEN }} 75 | # args: --all-targets --all-features --workspace --no-deps 76 | 77 | cargo-fmt: 78 | runs-on: ubuntu-latest 79 | 80 | steps: 81 | - name: Checkout 82 | uses: actions/checkout@v2 83 | 84 | - name: Install latest stable 85 | uses: dtolnay/rust-toolchain@stable 86 | with: 87 | toolchain: stable 88 | components: rustfmt 89 | 90 | - name: deal with rust cache 91 | uses: Swatinem/rust-cache@v1 92 | 93 | - name: cargo fmt 94 | run: cargo fmt --all -- --check 95 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## [v0.2.3](https://github.com/BobAnkh/ns3-parallel/releases/tag/v0.2.3) - 2022-11-02 13:30:08+00:00 4 | 5 | Refactor code to support multiple config format: toml, ron, json, yaml. 6 | 7 | ### Feature 8 | 9 | - config: 10 | - support multiple config format ([6b8f95c](https://github.com/BobAnkh/ns3-parallel/commit/6b8f95c900325f989191430580f5ff1fe4890b5c)) 11 | 12 | ### Documentation 13 | 14 | - readme: 15 | - update contributors ([5c4cdfb](https://github.com/BobAnkh/ns3-parallel/commit/5c4cdfb619be1d89ab22e7c39027571ff064adfb)) 16 | 17 | ## [v0.2.2](https://github.com/BobAnkh/ns3-parallel/releases/tag/v0.2.2) - 2022-02-09 09:55:21 18 | 19 | Improve per run performance by replace `--run` with `--run-no-build` to avoid build time. 20 | 21 | ### Performance Improvements 22 | 23 | - exec: 24 | - remove build time for per run ([4666b76](https://github.com/BobAnkh/ns3-parallel/commit/4666b76be5c5dad2bfc7abdc34d6f88027c408c7)) 25 | 26 | ## [v0.2.1](https://github.com/BobAnkh/ns3-parallel/releases/tag/v0.2.1) - 2022-02-08 08:51:25 27 | 28 | - refactor inner function for generalizability 29 | 30 | ### Documentation 31 | 32 | - readme: 33 | - update badges ([7ba04cc](https://github.com/BobAnkh/ns3-parallel/commit/7ba04ccd7bff1bfdbaf511fa08494dfd223b2c6a)) 34 | - update badges ([d2da5d4](https://github.com/BobAnkh/ns3-parallel/commit/d2da5d4730d97a4174513522b7753eca78d3e08a)) 35 | 36 | ### Refactor 37 | 38 | - exec: 39 | - use more generic interface ([75bc1d2](https://github.com/BobAnkh/ns3-parallel/commit/75bc1d29f542e40433fb4ff061850b10a8045336)) 40 | 41 | ## [v0.2.0](https://github.com/BobAnkh/ns3-parallel/releases/tag/v0.2.0) - 2022-01-25 09:24:54 42 | 43 | - Seperate NS3 build part, providing stderr when build fails 44 | - Add more document on how to use it in example 45 | 46 | ### Feature 47 | 48 | - ns3: 49 | - seperate ns3 build ([9ca99b4](https://github.com/BobAnkh/ns3-parallel/commit/9ca99b4c9a5e8cf175a1321dcb7df810db550bce)) 50 | 51 | ### Documentation 52 | 53 | - example: 54 | - add more comments ([43a64ea](https://github.com/BobAnkh/ns3-parallel/commit/43a64eaa04b47e13d5d8dc1470eaabf3c1b655f2)) 55 | 56 | - readme: 57 | - add some badges ([71634bc](https://github.com/BobAnkh/ns3-parallel/commit/71634bcf51b571a8372e4cd3de586f9ea8d6ba85)) 58 | 59 | ## [v0.1.0](https://github.com/BobAnkh/ns3-parallel/releases/tag/v0.1.0) - 2022-01-23 09:54:21 60 | 61 | *No description* 62 | 63 | ### Feature 64 | 65 | - lib: 66 | - add basic version ([01b1175](https://github.com/BobAnkh/ns3-parallel/commit/01b11755b305dff19d6037aa310f5444e7de25d9)) 67 | 68 | ### Documentation 69 | 70 | - readme: 71 | - update contributors ([fe0a51e](https://github.com/BobAnkh/ns3-parallel/commit/fe0a51ebbbf94ba44f994eb4cd3069300d8c4501)) 72 | 73 | \* *This CHANGELOG was automatically generated by [auto-generate-changelog](https://github.com/BobAnkh/auto-generate-changelog)* 74 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ## Description 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ## How Has This Been Tested 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ## Screenshots(optional) 27 | 28 | 29 | 30 | 31 | 32 | ## Types of changes 33 | 34 | 35 | 36 | 37 | - Bug fix (non-breaking change which fixes an issue) 38 | - New feature (non-breaking change which adds functionality) 39 | - Documentation (non-breaking change which updates documentation) 40 | - Breaking change (fix or feature that would cause existing functionality to change) 41 | - Code style (formatting, renaming) 42 | - Refactoring (no functional changes, no api changes) 43 | - Other (please describe here): 44 | 45 | ## Checklist 46 | 47 | 48 | 49 | 50 | - [ ] Code follows the code style of this project. 51 | - [ ] Changes follow the **CONTRIBUTING** guidelines. 52 | - [ ] Update necessary documentation accordingly. 53 | - [ ] Lint and tests pass locally with the changes. 54 | - [ ] Check issues and pull requests first. You don't want to duplicate effort. 55 | 56 | ## Other information 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ns3-parallel 2 | 3 | [![github-repo](https://img.shields.io/badge/github-BobAnkh/ns3--parallel-f5dc23?logo=github)](https://github.com/BobAnkh/ns3-parallel) 4 | [![crates.io](https://img.shields.io/crates/v/ns3-parallel.svg?logo=rust)](https://crates.io/crates/ns3-parallel) 5 | [![docs.rs](https://img.shields.io/badge/docs.rs-ns3--parallel-blue?logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K)](https://docs.rs/ns3-parallel) 6 | [![LICENSE Apache-2.0](https://img.shields.io/github/license/BobAnkh/ns3-parallel?logo=Apache)](https://github.com/BobAnkh/ns3-parallel/blob/main/LICENSE) 7 | 8 | A Multitask Parallel Concurrent Executor for ns-3 (network simulator). 9 | 10 | ## Usage 11 | 12 | Define your config struct and param struct, implement trait `BuildParam` for the first and trait `BuildCmd` for the second. 13 | 14 | Then call the `ExecutorBuilder` to build a `Executor`. Then launch the tasks, wait for the results. 15 | 16 | Examples see `examples/simple.rs`. 17 | 18 | To run the example, you can first execute the script `setup-ns3.sh` then execute `cargo run --example simple` in the root directory. 19 | 20 | Currently support 4 config file formats: toml, ron, json, yaml. Example config files can see `config.toml` and `config.ron` under root. **Welcome contributions for any new config format**. 21 | 22 | ## Maintainer 23 | 24 | [@BobAnkh](https://github.com/BobAnkh) 25 | 26 | ## How to contribute 27 | 28 | You should follow our [Code of Conduct](/CODE_OF_CONDUCT.md). 29 | 30 | See [CONTRIBUTING GUIDELINES](/CONTRIBUTING.md) for contributing conventions. 31 | 32 | Make sure to pass all the tests before submitting your code. 33 | 34 | ### Contributors 35 | 36 | 37 | 38 | 45 | 46 |
39 | 40 | Yixin 41 |
42 | Yixin Shen 43 |
44 |
47 | 48 | ## LICENSE 49 | 50 | [Apache-2.0](LICENSE) © BobAnkh 51 | -------------------------------------------------------------------------------- /.github/workflows/cargo-test.yml: -------------------------------------------------------------------------------- 1 | name: Cargo Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | pull_request: 9 | types: [ready_for_review, opened, synchronize, reopened] 10 | paths: 11 | - '**.rs' 12 | - '**/Cargo.toml' 13 | workflow_dispatch: 14 | 15 | jobs: 16 | cargo-test: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v2 22 | 23 | - name: Install latest nightly 24 | uses: actions-rs/toolchain@v1 25 | with: 26 | toolchain: stable 27 | override: true 28 | components: rustfmt, clippy 29 | - name: deal with rust cache 30 | uses: Swatinem/rust-cache@v1 31 | - name: cargo test 32 | run: | 33 | cargo test --no-fail-fast --verbose 34 | 35 | # cargo-coverage-test: 36 | # runs-on: ubuntu-latest 37 | # env: 38 | # BACKEND_TEST_MODE: true 39 | # defaults: 40 | # run: 41 | # working-directory: backend 42 | 43 | # steps: 44 | # - name: Checkout 45 | # uses: actions/checkout@v2 46 | 47 | # - name: Install latest nightly 48 | # uses: actions-rs/toolchain@v1 49 | # with: 50 | # toolchain: stable 51 | # override: true 52 | # components: rustfmt, clippy 53 | # - name: deal with rust cache 54 | # uses: Swatinem/rust-cache@v1 55 | # with: 56 | # working-directory: backend 57 | # - name: Add containers 58 | # run: docker-compose -f docker-compose-dev.yml up -d 59 | # - name: run backend consumer 60 | # run: | 61 | # cargo install cargo-tarpaulin 62 | # - name: Generate code coverage 63 | # run: | 64 | # cargo install cargo-tarpaulin 65 | # # cargo tarpaulin --all-features --no-run --skip-clean --no-fail-fast --verbose --timeout 300 --out Xml 66 | # # ./target/debug/consumer & 67 | # cargo tarpaulin --all-features --no-fail-fast --skip-clean --verbose --timeout 300 --out Xml --exclude-files "src/bin/*" --follow-exec 68 | # - name: remove containers 69 | # run: docker-compose -f docker-compose-dev.yml down && sudo rm -rf data 70 | # - name: Upload to codecov.io 71 | # uses: codecov/codecov-action@v2 72 | # if: ${{ success() }} 73 | # with: 74 | # directory: backend 75 | 76 | # cargo-bench: 77 | # runs-on: ubuntu-latest 78 | # env: 79 | # BACKEND_TEST_MODE: true 80 | # defaults: 81 | # run: 82 | # working-directory: backend 83 | 84 | # steps: 85 | # - name: Checkout 86 | # uses: actions/checkout@v2 87 | 88 | # - name: Install latest nightly 89 | # uses: actions-rs/toolchain@v1 90 | # with: 91 | # toolchain: stable 92 | # override: true 93 | # components: rustfmt, clippy 94 | # - name: deal with rust cache 95 | # uses: Swatinem/rust-cache@v1 96 | # with: 97 | # working-directory: backend 98 | # - name: cargo bench 99 | # run: | 100 | # cargo bench --all-features -v --no-fail-fast 101 | 102 | -------------------------------------------------------------------------------- /src/core.rs: -------------------------------------------------------------------------------- 1 | //! Core traits for the library 2 | 3 | /// # BuildParam 4 | /// 5 | /// This trait is used to build the parameters for the NS3 program. 6 | /// 7 | /// Implement this trait and also the `Default` trait on your own config struct. 8 | /// 9 | /// ## Example 10 | /// 11 | /// ``` 12 | /// use serde::{Deserialize, Serialize}; 13 | /// use ns3_parallel::{BuildParam, BuildCmd}; 14 | /// 15 | /// #[derive(Debug, Serialize, Deserialize)] 16 | /// #[serde(default)] 17 | /// pub struct Config { 18 | /// pub sim_time: u32, 19 | /// pub app_name: String, 20 | /// pub policy: Vec, 21 | /// } 22 | /// 23 | /// #[derive(Debug, Clone, Serialize, Deserialize)] 24 | /// pub struct Param { 25 | /// pub sim_time: u32, 26 | /// pub app_name: String, 27 | /// pub policy: u32, 28 | /// } 29 | /// 30 | /// impl Default for Config { 31 | /// fn default() -> Self { 32 | /// Config { 33 | /// sim_time: 100, 34 | /// app_name: "ns3-tcp-bbr".to_string(), 35 | /// policy: vec![1, 2, 3], 36 | /// } 37 | /// } 38 | /// } 39 | /// 40 | /// impl BuildParam for Config { 41 | /// fn build_param(&self) -> Vec { 42 | /// let mut params: Vec = Vec::new(); 43 | /// for policy in &self.policy { 44 | /// let param = Param { 45 | /// sim_time: self.sim_time, 46 | /// app_name: self.app_name.clone(), 47 | /// policy: *policy, 48 | /// }; 49 | /// params.push(param); 50 | /// } 51 | /// params 52 | /// } 53 | /// } 54 | /// impl BuildCmd for Param { 55 | /// fn build_cmd(&self) -> String { 56 | /// format!( 57 | /// "xxx --app-name={} --sim-time={} --policy={}", 58 | /// self.app_name, self.sim_time, self.policy 59 | /// ) 60 | /// } 61 | /// } 62 | pub trait BuildParam { 63 | fn build_param(&self) -> Vec

; 64 | } 65 | 66 | /// # BuildCmd 67 | /// 68 | /// This trait is used to build the command line for the NS3 program. 69 | /// 70 | /// Implement this trait on your own param struct. 71 | /// 72 | /// ## Example 73 | /// 74 | /// ``` 75 | /// use serde::{Deserialize, Serialize}; 76 | /// use ns3_parallel::{BuildParam, BuildCmd}; 77 | /// 78 | /// #[derive(Debug, Serialize, Deserialize)] 79 | /// #[serde(default)] 80 | /// pub struct Config { 81 | /// pub sim_time: u32, 82 | /// pub app_name: String, 83 | /// pub policy: Vec, 84 | /// } 85 | /// 86 | /// #[derive(Debug, Clone, Serialize, Deserialize)] 87 | /// pub struct Param { 88 | /// pub sim_time: u32, 89 | /// pub app_name: String, 90 | /// pub policy: u32, 91 | /// } 92 | /// 93 | /// impl Default for Config { 94 | /// fn default() -> Self { 95 | /// Config { 96 | /// sim_time: 100, 97 | /// app_name: "ns3-tcp-bbr".to_string(), 98 | /// policy: vec![1, 2, 3], 99 | /// } 100 | /// } 101 | /// } 102 | /// 103 | /// impl BuildParam for Config { 104 | /// fn build_param(&self) -> Vec { 105 | /// let mut params: Vec = Vec::new(); 106 | /// for policy in &self.policy { 107 | /// let param = Param { 108 | /// sim_time: self.sim_time, 109 | /// app_name: self.app_name.clone(), 110 | /// policy: *policy, 111 | /// }; 112 | /// params.push(param); 113 | /// } 114 | /// params 115 | /// } 116 | /// } 117 | /// impl BuildCmd for Param { 118 | /// fn build_cmd(&self) -> String { 119 | /// format!( 120 | /// "xxx --app-name={} --sim-time={} --policy={}", 121 | /// self.app_name, self.sim_time, self.policy 122 | /// ) 123 | /// } 124 | /// } 125 | pub trait BuildCmd { 126 | fn build_cmd(&self) -> String; 127 | } 128 | -------------------------------------------------------------------------------- /examples/simple.rs: -------------------------------------------------------------------------------- 1 | use ns3_parallel::{executor::ConfigFormat, BuildCmd, BuildParam, Executor, ExecutorBuilder}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | // This is what you want to read from your configuration file. 5 | // Each part of the configuration file will be formed into a struct of this. 6 | // Fields not specified in your config file will use the default value defined in the Default trait. 7 | #[derive(Debug, Serialize, Deserialize)] 8 | #[serde(default)] 9 | pub struct MyConfig { 10 | pub sim_time: u32, 11 | pub app_name: String, 12 | pub policy: Vec, 13 | } 14 | 15 | // A set of parameters you need to execute ns3 program. 16 | // One param struct means one ns3 task. 17 | #[derive(Debug, Clone, Serialize, Deserialize)] 18 | pub struct MyParam { 19 | pub sim_time: u32, 20 | pub app_name: String, 21 | pub policy: u32, 22 | } 23 | 24 | // This trait impl will give you the default value of your config struct. 25 | // When a field is not specified in the config file, the default value will be used. 26 | impl Default for MyConfig { 27 | fn default() -> Self { 28 | MyConfig { 29 | sim_time: 100, 30 | app_name: "ns3-tcp-bbr".to_string(), 31 | policy: vec![1, 2, 3], 32 | } 33 | } 34 | } 35 | 36 | // From each of your config struct, you have to generate a vector of param struct. 37 | impl BuildParam for MyConfig { 38 | fn build_param(&self) -> Vec { 39 | let mut params: Vec = Vec::new(); 40 | for policy in &self.policy { 41 | let param = MyParam { 42 | sim_time: self.sim_time, 43 | app_name: self.app_name.clone(), 44 | policy: *policy, 45 | }; 46 | params.push(param); 47 | } 48 | params 49 | } 50 | } 51 | 52 | // From each of your param struct, you have to generate the command line passed to ns3 program. 53 | // The output of method build_cmd will be passed as the argument of "waf --run" in the command line. 54 | impl BuildCmd for MyParam { 55 | fn build_cmd(&self) -> String { 56 | format!( 57 | "simple-ns3 --app-name={} --sim-time={} --policy={}", 58 | self.app_name, self.sim_time, self.policy 59 | ) 60 | } 61 | } 62 | 63 | #[tokio::main] 64 | async fn main() { 65 | // ========== Use toml format as the config file ========== 66 | // Use ExecutorBuilder to build your executor. 67 | let mut exe: Executor = ExecutorBuilder::new() 68 | .config_path("config.toml") 69 | .config_format(ConfigFormat::Toml) 70 | .ns3_path("ns-allinone-3.33/ns-3.33/") 71 | .build() 72 | .unwrap(); 73 | 74 | // Run your executor. 75 | let _ = exe.execute().await.unwrap(); 76 | 77 | // Collect your results. 78 | let outputs = exe.get_outputs().to_owned(); 79 | 80 | // Here I just print all the results, you can do whatever you want with them here. 81 | for (_, output) in outputs { 82 | for task in output { 83 | println!("{}", task.stderr); 84 | } 85 | } 86 | 87 | // ========== Use ron format as the config file ========== 88 | // Use ExecutorBuilder to build your executor. 89 | let mut exe: Executor = ExecutorBuilder::new() 90 | .config_path("config.ron") 91 | .config_format(ConfigFormat::Ron) 92 | .ns3_path("ns-allinone-3.33/ns-3.33/") 93 | .task_concurrent(4) 94 | .retry_limit(2) 95 | .build() 96 | .unwrap(); 97 | 98 | // Run your executor. 99 | let _ = exe.execute().await.unwrap(); 100 | 101 | // Collect your results. 102 | let outputs = exe.get_outputs().to_owned(); 103 | 104 | // Here I just print all the results, you can do whatever you want with them here. 105 | for (_, output) in outputs { 106 | for task in output { 107 | println!("{}", task.stderr); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | thuburrow.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | We'd be glad for you to contribute to our source code and to make this project better! 4 | 5 | Feel free to submit a pull request or an issue, but make sure to use the templates 6 | 7 | It is **required to follow** the **`Language Style`** rules. It is **recommended to follow** the **`Commit Message Convention`** and **`Pull Request Convention`** **but not required**. 8 | 9 | ## Language Style 10 | 11 | Files of different languages should be checked locally according to the following conventions 12 | 13 | Commits should be made after all checks pass 14 | 15 | ### Rust 16 | 17 | Run `cargo fmt`(rustfmt) to format the code. 18 | 19 | Run `cargo clippy` to lint the code. 20 | 21 | Follow the official [naming convention](https://rust-lang.github.io/api-guidelines/naming.html). 22 | 23 | ### Shell 24 | 25 | Use `shellcheck` default configuration to check 26 | 27 | ## Commit Message Convention 28 | 29 | Each commit should contain relatively independent change (that is, a hodgepodge of multiple types of modifications is not allowed to be submitted in one commit), and the specific changes need to be clarified in the message 30 | 31 | The commit message conventions of this project mainly refers to the most widely used [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w) 32 | 33 | Here is the message format: 34 | 35 | > `(): ` 36 | > 37 | > // blank line 38 | > 39 | > `` 40 | > 41 | > // blank line 42 | > 43 | > `