Simulate an OpenFlow learning controller
Handle simulated Packet-In events, install and inspect learning-switch flows, then prove an IoT-isolation policy with priorities, counters, receiver results, and cleanup.

Cloud Clara: I want you to connect controller intent to table state, counters, receiver behavior, protected paths, and cleanup.
Predict the reading, then compare it with the measurement.
Python 3 in your browser (JupyterLite)
Python · no installHandle simulated Packet-In events, install and inspect learning-switch flows, then prove an IoT-isolation policy with priorities, counters, receiver results, and cleanup.
Open the notebook in your browser and run each Python cell; no install or account is needed.
Three ways to run: use JupyterLite here with no install; run main.py locally from the downloadable lab folder; or open the same notebook in Google Colab.
Steps
Step 1
- Do
- Run `python3 main.py --step 1` to inspect the simulated two-switch topology and initial table-miss rule.
- You will see
- The topology names sensor, laptop, telemetry, and admin endpoints; s1-edge's table contains priority 0, match `*`, action CONTROLLER, and zero packets.
- Why it matters
- The explicit table-miss establishes why an unknown packet reaches control logic instead of disappearing silently.

Step 1 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 2
- Do
- Run `python3 main.py --step 2` to send the first frame to an unknown destination.
- You will see
- The table miss emits `PACKET_IN reason=NO_MATCH`, the controller learns the source on port 1, and PACKET_OUT floods because the destination is unknown.
- Why it matters
- The event shows which state can be learned safely from ingress and why no destination-specific rule exists yet.

Step 2 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 3
- Do
- Run `python3 main.py --step 3` to deliver the reply and install forward and reverse learned flows.
- You will see
- Two FLOW_MOD lines show priority 100 matches and output ports; the barrier reply confirms that the switch accepted two learned rules.
- Why it matters
- Controller intent becomes reviewable switch state only after the matches, actions, and acknowledgement are visible.

Step 3 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 4
- Do
- Run `python3 main.py --step 4` to print the resulting s1-edge flow table.
- You will see
- The table lists two priority-100 learned entries above the priority-0 table miss, with match, action, and packet-count columns.
- Why it matters
- A table dump proves final ordering and preserves the fallback path for addresses the controller has not learned.

Step 4 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 5
- Do
- Run `python3 main.py --step 5` to repeat the forward packet after its rule is installed.
- You will see
- The frame matches priority 100, outputs to port 2, increments its packet counter from 0 to 1, emits no Packet-In, and reaches laptop-1.
- Why it matters
- The match, counter movement, controller absence, and receiver result together prove data-plane handling.

Step 5 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 6
- Do
- Run `python3 main.py --step 6` to install a higher-priority IoT-isolation policy.
- You will see
- FLOW_MOD lines and the full table show priority 300 DROP for IoT-to-admin and priority 200 OUTPUT:3 for IoT-to-telemetry above learned rules and table miss.
- Why it matters
- Narrow policy matches and explicit priorities keep a broad learning rule from bypassing the protected admin boundary.

Step 6 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 7
- Do
- Run `python3 main.py --step 7` to test one allowed telemetry packet and one denied admin packet.
- You will see
- Packet A reaches telemetry through priority 200; packet B matches priority 300 DROP with receiver NONE; allow and deny counters both become 1.
- Why it matters
- Both positive and protected-path tests are needed to prove isolation without breaking the permitted IoT service.

Step 7 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 8
- Do
- Run `python3 main.py --step 8` to remove the temporary isolation rules and close the proof record.
- You will see
- The table shrinks from five to three entries after deleting priorities 200 and 300; the evidence line retains Packet-In, Flow-Mod, barrier, counters, receiver results, and cleanup.
- Why it matters
- Explicit cleanup prevents maintenance policy from becoming hidden permanent state and completes the protocol evidence chain.

Step 8 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab)
Chapter checks
These questions refer to the chapter’s examples. Use the return links to review their answers.
During a maintenance window, a controller must steer gateway update downloads without catching telemetry, door-control events, or management access. Which first check keeps the OpenFlow-style rule change traceable?
Return to the chapter’s knowledge checkA controller sends a flow-mod to steer update traffic, and the switch accepts it. What proof is still needed before saying the service behavior worked?
Return to the chapter’s knowledge checkA controller sends two OpenFlow-style changes for a gateway maintenance window: remove an old broad update rule, then install a narrower rule with protected exceptions. Which proof closes the protocol boundary?
Return to the chapter’s knowledge check