Skip to main content
IT BIBLESign in

Team labs

Labs for two people

Write a networking lab that two teammates work on together, each on their own router.

A lab for two lets two people on your team work on the same simulated network at the same time. Each person controls their own router. They cable the routers together, and the lab is finished when what they do together passes every task.

For now both people work on simulated MikroTik routers (engine routeros). The people must be on the same team, and the team's plan must be active.

How it works for the learners

  1. One person starts the lab. They see their own router and an address to share.
  2. A teammate opens the address and chooses Join the lab. They get the other router.
  3. Each person types on their own router only. They can see their teammate's name and which devices are theirs, but not the other router's screen.
  4. A task is ticked off for both of them as soon as the work passes, whoever's work it was.
  5. When every task is done, Finish lab completes the lab for both people.

Every line is sent to the server, which decides what it prints. This matters for ping: the answer depends on the other router as it is at that moment, so a ping can fail until your teammate has set their address, and succeed right after. What each person sees is exactly what is graded.

Writing the lab

A lab for two is an ordinary lab file with three additions:

Field What it is
players Set to 2.
nodes[].player 1 or 2: who controls this router. The person who starts the lab is player 1. Each player needs at least one router.
links The cables. Each is { "a": { "node": "router-a", "port": "ether2" }, "b": { "node": "router-b", "port": "ether2" } }.

Every node must be a simulated router: "type": "simulator", "engine": "routeros" and a profile such as mikrotik-hex. Labs for one person cannot have players, links or player.

What a cable does

A router answers a ping from a router it is cabled to when:

  • the address being pinged is on the other router's cabled port, and not switched off, and
  • the router sending the ping has an address on its own cabled port in the same network.

So with a cable between ether2 of both routers, 10.0.0.1/24 on one and 10.0.0.2/24 on the other, each can ping the other. If the addresses are on different networks, on a port that is not cabled, or switched off, the ping gets no answer.

Checks

A task checks the state of any router, so one task can look at both. A check on router-a that the ping worked looks at ran, which holds ping:<address> after a ping got an answer. Checks on addresses use ipAddress.

A complete example

{
  "schemaVersion": 1,
  "id": "link-two-routers",
  "version": "1.0.0",
  "title": "Link two routers",
  "description": "Give each router an address on the cable and ping across it.",
  "track": "networking",
  "difficulty": "beginner",
  "estimatedMinutes": 15,
  "access": { "tier": "subscriber" },
  "session": { "maxMinutes": 45, "idleMinutes": 10 },
  "players": 2,
  "links": [
    { "a": { "node": "router-a", "port": "ether2" }, "b": { "node": "router-b", "port": "ether2" } }
  ],
  "nodes": [
    { "id": "router-a", "type": "simulator", "engine": "routeros", "profile": "mikrotik-hex", "terminal": true, "player": 1 },
    { "id": "router-b", "type": "simulator", "engine": "routeros", "profile": "mikrotik-hex", "terminal": true, "player": 2 }
  ],
  "steps": [
    {
      "id": "address-both",
      "title": "Give both routers an address",
      "instructions": "Player 1 gives `ether2` the address `10.0.0.1/24`. Player 2 gives `ether2` the address `10.0.0.2/24`.\n\nUse `/ip address add address=... interface=ether2`.",
      "checks": [
        {
          "type": "state",
          "node": "router-a",
          "expect": { "ipAddress": [{ "address": "10.0.0.1/24", "interface": "ether2" }] },
          "failureMessage": "Player 1 needs 10.0.0.1/24 on ether2."
        },
        {
          "type": "state",
          "node": "router-b",
          "expect": { "ipAddress": [{ "address": "10.0.0.2/24", "interface": "ether2" }] },
          "failureMessage": "Player 2 needs 10.0.0.2/24 on ether2."
        }
      ]
    },
    {
      "id": "ping-across",
      "title": "Ping your teammate",
      "instructions": "Player 1 pings `10.0.0.2`. Then player 2 pings `10.0.0.1`.",
      "checks": [
        { "type": "state", "node": "router-a", "expect": { "ran": ["ping:10.0.0.2"] }, "failureMessage": "Player 1's ping did not get an answer." },
        { "type": "state", "node": "router-b", "expect": { "ran": ["ping:10.0.0.1"] }, "failureMessage": "Player 2's ping did not get an answer." }
      ]
    }
  ]
}

Finishing and webhooks

When the lab is finished, both people have completed it. Each completion is reported to your team's webhooks as its own member.lab_completed event. See Events and payloads.