Rumba is a Python framework that allows users to write Python scripts to define recursive internet networks and run scripted experiments. The original documentation can be found [here](https://arcfire.gitlab.io/rumba/). This version of rumba is maintained by the Ouroboros (O7s) project. The documentation can be found [here](https://ouroboros.rocks/wiki/Rumba). ## Installation To install Rumba from a local clone: ```bash git clone https://codeberg.org/o7s/rumba.git cd rumba python3 -m venv .venv source .venv/bin/activate pip install . ``` Optional extras: ```bash pip install rumba[docker] # Docker testbed backend pip install rumba[NumpyAcceleration] # faster random traffic generation pip install rumba[graphs] # PDF graph export via pydot pip install rumba[visualizer] # interactive visualization via igraph + plotly ``` On Debian/Ubuntu you may also need: ```bash sudo apt-get install build-essential libssl-dev libffi-dev python3-dev ``` The required dependency (`paramiko`) is installed automatically. ## Defining a Topology Rumba models recursive networks using **layers** and **nodes**. Layers correspond to Ouroboros IPCP types. Nodes declare which layers they belong to and how those layers are stacked via **registrations**. The example below defines four nodes connected in a ring, with a single unicast layer (`n1`) running over four point-to-point Ethernet links: ``` a ---e01--- b | | e04 e02 | | d ---e03--- c ``` ```python from rumba.model import UnicastLayer, EthDixLayer, Node # A unicast layer that will span all four nodes n1 = UnicastLayer("n1") # Four point-to-point Ethernet links (max 2 members each) e01 = EthDixLayer("e01") # a <-> b e02 = EthDixLayer("e02") # b <-> c e03 = EthDixLayer("e03") # c <-> d e04 = EthDixLayer("e04") # d <-> a # Each node lists its layer memberships and how layers are stacked. # registrations = {upper: [lower, ...]} means "upper registers in lower". a = Node("a", layers=[n1, e01, e04], registrations={n1: [e01, e04]}) b = Node("b", layers=[n1, e01, e02], registrations={n1: [e01, e02]}) c = Node("c", layers=[n1, e02, e03], registrations={n1: [e02, e03]}) d = Node("d", layers=[n1, e03, e04], registrations={n1: [e03, e04]}) ``` Two nodes that share an `EthDixLayer` are connected by that Ethernet link. The `registrations` dictionary tells Rumba how to stack the layers: `{n1: [e01, e04]}` means the unicast layer `n1` registers in both `e01` and `e04` on that node, giving it connectivity over those links. Policies can be set on unicast layers: ```python n1.add_policy("routing", "lfa") ``` Link quality (delay, loss, rate) can be configured on Ethernet layers: ```python from rumba.model import EthDixLayer, Delay e01 = EthDixLayer("e01") e01.set_delay(delay=10, jitter=2) # 10 ms delay, 2 ms jitter e01.set_loss(loss=0.1) # 0.1% packet loss e01.set_rate(rate=100) # 100 Mbps ``` ## Quick Start A complete runnable script that deploys the ring topology above on a local testbed: ```python from rumba.model import * from rumba.utils import ExperimentManager import rumba.testbeds.local as local import rumba.prototypes.ouroboros as our # --- topology (from the example above) --- n1 = UnicastLayer("n1") e01 = EthDixLayer("e01") e02 = EthDixLayer("e02") e03 = EthDixLayer("e03") e04 = EthDixLayer("e04") a = Node("a", layers=[n1, e01, e04], registrations={n1: [e01, e04]}) b = Node("b", layers=[n1, e01, e02], registrations={n1: [e01, e02]}) c = Node("c", layers=[n1, e02, e03], registrations={n1: [e02, e03]}) d = Node("d", layers=[n1, e03, e04], registrations={n1: [e03, e04]}) # --- testbed and experiment --- tb = local.Testbed() exp = our.Experiment(tb, nodes=[a, b, c, d]) # --- run --- with ExperimentManager(exp): exp.swap_in() # provision the testbed exp.bootstrap_prototype() # create IPCPs and enrollments ``` `swap_in()` provisions the nodes on the chosen testbed. `bootstrap_prototype()` creates the Ouroboros IPCPs, bootstraps them, and performs enrollments automatically. `ExperimentManager` handles cleanup when the block exits. ## Key Concepts - **Layer** — a network layer aligned with an Ouroboros IPCP type. Available types: `UnicastLayer`, `BroadcastLayer`, `EthDixLayer`, `EthLlcLayer`, `LocalLayer`, `Udp4Layer`, `Udp6Layer`. - **Node** — a system declaring its layer memberships and registrations (layer stacking). - **Testbed** — the infrastructure backend that provisions nodes (see table below). - **Experiment** — computes IPCP placement, enrollment order, and manages the prototype lifecycle. - **StoryBoard** — schedules client/server traffic with support for Poisson arrival rates. - **CommandResult** — structured result from `node.execute_command()` carrying exit code, stdout, and stderr. - **Process** — a managed background process with `is_alive()`, `wait()`, and `kill()`. - **ExperimentManager** — context manager that handles experiment setup and teardown. ## Supported Testbeds | Testbed | Module | Description | |----------|---------------------------|------------------------------------------------| | Local | `rumba.testbeds.local` | Single machine, processes run locally | | LocalNet | `rumba.testbeds.localnet` | Linux bridges + veth pairs, supports netem | | Docker | `rumba.testbeds.dockertb` | Docker containers with bridge networking | | Emulab | `rumba.testbeds.emulab` | Emulab / iMinds testbed (SSH-based) | | jFed | `rumba.testbeds.jfed` | Virtual Wall, ExoGENI, CloudLab via jFed | ## CLI Tools The `rumba-access` command opens an SSH session to an experiment node: ```bash rumba-access ``` ## More Examples See the [examples/](examples/) directory for additional topologies and usage patterns, including multi-layer stacking, Docker deployments, storyboard scripting, and large-scale experiments. ## Citation If you use Rumba in your research, please cite: > S. Vrijders, D. Staessens, M. Capitani, and V. Maffione, > "Rumba: A Python framework for automating large-scale recursive > internet experiments on GENI and FIRE+," *IEEE*, 2018. ## Versioning Rumba uses `setuptools_scm` to derive its version from git tags. **Compatibility contract across Ouroboros repositories:** | Scope | Rule | |---|---| | ouroboros (C) ↔ pyouroboros / rumba | Shared `major.minor` — rumba requires at least the same ouroboros `major.minor` | | pyouroboros ↔ rumba ↔ ouroboros-integration | Strict lockstep `major.minor.patch` — always released together | ## License Rumba is licensed under the [GNU Lesser General Public License v2.1](LICENSE). See [AUTHORS](AUTHORS) for the list of contributors.