A two-day regional final: eight teams, a stage with two five-seat booths, 1,500 spectators, casters, observers, replay, and a live broadcast watched by tens of thousands. The players need the fairest, quietest network in the building; the production needs the busiest; and the two must never meet. We build it on Cisco from the stage outwards in 11 tested steps.
Full network · all steps built
highlighted = lines added in the selected step · earlier steps shown plain · later steps hidden
This is part 8 of the Build series, and the big brother of the gaming center. There, the threat was customers attacking each other and the goal was low latency for everyone. Here, ten people on a stage are playing for prize money in front of an audience, and the network has three new jobs: give both teams exactly the same path to the match server, make sure no player can see the broadcast (which would reveal the other team's positions), and keep enough evidence to settle a dispute about lag.
At the same time, a production team is moving a dozen high-bitrate video feeds around the building and sending the finished show to the world twice over. The design keeps those two worlds on separate hardware, connected only where the rules say.
01
A fictional regional final in a 1,500-seat arena. The tournament operator owns the rules; the network has to enforce some of them.
Two teams of five play on stage at a time, in booths on either side of a central stage rack that holds two match servers (main and hot spare) and the referee's console. Six more teams warm up in a bootcamp room with 40 PCs and practice servers. The production gallery has four observer PCs (in-game camera operators), replay and graphics machines, the casters' feeds, and two encoders. A press room has wired desks. The arena has public Wi-Fi for spectators. The tournament runs on the publisher's platform, which needs the players' PCs to log in and run the publisher's anti-cheat.
| Requirement | Where it comes from, and what it forces |
|---|---|
| R1 Fair paths | Both teams must have the same latency to the match server. Same switch, same port type, same cable length, one hop. |
| R2 No ghosting | A player watching the live broadcast would see the opponents' positions. Players get no route to any stream or video site, only an allowlist. |
| R3 Delayed spectating | Observers watch the match through the server's spectator port, which runs on a delay. Production reaches that port and nothing else on the stage. |
| R4 Evidence for disputes | "My game lagged" claims are settled with data. All stage traffic is recorded for the length of the event. |
| R5 Broadcast never drops | The show leaves the building twice, from two encoders over two ISPs. |
| R6 Production bandwidth | Twelve NDI video feeds at ~125–250 Mb/s each move around the gallery. 10G everywhere in production, and multicast under control. |
| R7 Spectators stay out | 1,500 phones on public Wi-Fi with no path to anything that matters, and a hard per-device limit. |
| R8 Change freeze | Nothing is changed on match days except by the network lead, with the tournament director's approval. |
02
Each one exists because an esports final is judged on fairness first and speed second.
Players and match servers live on the same switch, a C9300-24UX in the stage rack, but in different VLANs, so an ACL can sit between them. If that switch only did Layer 2, every packet between a player and the server would go to the core and back. So STAGE-SW routes its own pod: player-to-server traffic is one switch, one routing lookup, for both teams. Its single routed uplink to the core is the pod's only door, and that door has its own ACL.
Players need the publisher's login, matchmaking and anti-cheat services, which run on large cloud and CDN address ranges that change constantly. An IP allowlist would break mid-match. Instead, players use a tournament resolver that only answers the domain names in the publisher's tournament guide; every other name gets "does not exist". The switch ACL blocks any other DNS and anything that isn't HTTPS. The locked player image (no admin rights, encrypted DNS disabled) closes what the network can't.
A SPAN session on STAGE-SW copies every packet of every player port and both servers to a capture box with a rolling 48-hour buffer. That's a few hundred GB for a two-day event, a cheap disk, and the end of most lag disputes, because the referee can show the exact packet loss and latency for the seat and minute in question. Players agree to this in the tournament rules.
The broadcast doesn't rely on WAN failover. Two encoders send the same program over two ISPs to a cloud ingest that picks a healthy feed. A failing ISP costs nothing visible. The network's job is simply to keep each encoder on its own line, which is what policy routing does.
03
10.90.x.0/24, VLAN ID = third octet. The stage pod's three VLANs exist only on STAGE-SW.
| VLAN · subnet | Who lives here · where it's routed |
|---|---|
| 10 STAGE-PLAYERS · 10.90.10.0/24 | Team A seats .11–.15, team B .16–.20. Static. Routed on STAGE-SW. |
| 15 MATCH-SERVERS · 10.90.15.0/24 | Main .11, hot spare .12. Routed on STAGE-SW. |
| 20 OPS · 10.90.20.0/24 | Referee .10, admin consoles .11–.12, tournament resolver DNS-ALLOW .53, capture box management .60. All in the stage rack; routed on STAGE-SW. |
| 11 BOOTCAMP · 10.90.11.0/24 | 40 practice PCs and practice servers. Routed on CORE. |
| 30 PRODUCTION · 10.90.30.0/24 | Observers .11–.14, replay/graphics, casters, encoders .21–.22, NDI Discovery Server .5. Routed on CORE. |
| 40 PRESS · 10.90.40.0/24 | Press desks and press Wi-Fi. Routed on CORE. |
| 50 PUBLIC · 10.90.48.0/21 | Spectator Wi-Fi. Terminated on the EDGE, never routed by the core. |
| 99 MGMT · 10.90.99.0/24 | All switches, APs, EDGE. Transit links: 10.90.255.0/24 in /30s. |
04
Rows start, columns receive. Default deny. The Stage players column is empty except for Ops.
The Production → Match servers cell is the only door into the stage pod from outside, and it's one UDP port: the server's delayed spectator feed. The Stage players column is closed to everyone except the referee and admins. That's what makes "a spectator interfered with a match" a claim the network can rule out.
04b
Every requirement from the brief, the steps that implement it, the config that does it, and the test that proves it.
| Requirement | Implemented in | Key config | Proven by |
|---|---|---|---|
| R1 Fair paths | step 1 | both teams and the servers on STAGE-SW; matched cables; EEE off; routed pod | "Fair paths" drill, section 16 |
| R2 No ghosting | step 6 | DNS-ALLOW resolver; V10-IN blocks other DNS; HTTPS only | "No ghosting" drill |
| R3 Delayed spectating | step 6 | UPLINK-IN permits only UDP 27020 from production | "Delayed spectating" drill |
| R4 Evidence for disputes | step 7 | SPAN session 1 to Te1/0/24; 48 h ring buffer | "Dispute drill" |
| R5 Broadcast never drops | step 8 · step 9 | PBR keeps encoder 1 on ISP B; two SRT feeds to the cloud | "Broadcast resilience" drill |
| R6 Production bandwidth | step 3 | 10G production switch; NDI Discovery Server; IGMP snooping + querier | "Production load" drill |
| R7 Spectators stay out | step 4 · step 8 | public terminated on the edge; no PUBLIC → OUTSIDE-B pair; 1 Mb/s per client | "Crowd" drill |
| R8 Change freeze | step 11 | archive log config; baseline copy; configure replace | "Freeze and rollback" drill |
The build
The stage pod first, because everything else is built around protecting it. Every step ends with a checkpoint.
Eleven steps: the stage pod, the bootcamp room, production, front of house, the core, competition integrity, dispute capture, the edge with two ISPs, the broadcast, WAN queuing, and match-day operations. The final "scrim day" rehearsal (section 16) runs a full match with the whole crew before doors open.
05 · Step 1 of 11
Ten player PCs, two match servers and the referee on one switch that routes its own pod, cabled so neither team is a metre closer to the server.
▲ Show step 1 in the interactive topology · see what this step adds, and click any device for its config
hostname STAGE-SW
ip routing
vlan 10
name STAGE-PLAYERS
vlan 15
name MATCH-SERVERS
vlan 20
name OPS
!
interface range TenGigabitEthernet1/0/1 - 5
description TEAM A seats 1-5 (3 m cables, same batch as team B)
switchport mode access
switchport access vlan 10
switchport port-security maximum 1
switchport port-security mac-address sticky
switchport port-security
no power efficient-ethernet
spanning-tree portfast
spanning-tree bpduguard enable
interface range TenGigabitEthernet1/0/6 - 10
description TEAM B seats 1-5 (3 m cables, same batch as team A)
! … identical to team A, line for line
interface range TenGigabitEthernet1/0/11 - 12
description MATCH SERVERS (main, hot spare)
switchport mode access
switchport access vlan 15
no power efficient-ethernet
spanning-tree portfast
interface range TenGigabitEthernet1/0/13 - 14
description REFEREE + capture-box management
switchport mode access
switchport access vlan 20
spanning-tree portfast
!
interface TenGigabitEthernet1/1/1
description CORE (the pod's only door)
no switchport
ip address 10.90.255.2 255.255.255.252
interface Vlan10
ip address 10.90.10.1 255.255.255.0
interface Vlan15
ip address 10.90.15.1 255.255.255.0
interface Vlan20
ip address 10.90.20.1 255.255.255.0
ip route 0.0.0.0 0.0.0.0 10.90.255.1Both teams on one switch is the obvious part. Less obvious: identical cable lengths from the same batch; both teams' ports on the same forwarding ASIC (true for every port on a 24-port C9300; on larger switches, check which port groups share an ASIC); identical negotiated speed (check show interfaces status after the PCs are in, as one PC with an older NIC at 1G against nine at 2.5G is a fairness complaint waiting to happen); and Energy-Efficient Ethernet off, because its wake-up delay is tiny but not identical between NICs. Write all of it into the tournament's technical rules, so it was checked rather than assumed.
show interfaces status: all ten player ports at the same speed and duplex.sockperf, not Windows ping).show port-security: one sticky MAC per player port.06 · Step 2 of 11
Forty practice PCs and two practice servers in one flat VLAN. Practice isn't refereed, so it doesn't need the stage's strictness.
▲ Show step 2 in the interactive topology · see what this step adds, and click any device for its config
hostname BOOTCAMP-SW vlan 11 name BOOTCAMP interface range GigabitEthernet1/0/1 - 42 description BOOTCAMP PCs + practice servers switchport mode access switchport access vlan 11 spanning-tree portfast spanning-tree bpduguard enable interface TenGigabitEthernet1/1/1 description CORE switchport mode trunk switchport trunk allowed vlan 11,99
The bootcamp is deliberately ordinary: teams warm up, play online scrims against each other, and download patches. It gets the platform and the internet, but no path to the stage or to production. Keeping it on a separate switch means a team's patch download or a broken practice PC can't touch the stage switch's forwarding at all.
show vlan brief: Gi1/0/1–42 in VLAN 11.07 · Step 3 of 11
Observers, replay, graphics, casters and encoders moving video over IP. 10G to every machine, and multicast that only goes where it's asked for.
▲ Show step 3 in the interactive topology · see what this step adds, and click any device for its config
hostname PROD-SW
vlan 30
name PRODUCTION
ip igmp snooping
ip igmp snooping querier ! no multicast router in this VLAN
interface range TenGigabitEthernet1/0/1 - 14
description PRODUCTION machines (observers, replay, graphics, casters, encoders)
switchport mode access
switchport access vlan 30
spanning-tree portfast
interface range TenGigabitEthernet1/1/1 - 2
channel-group 3 mode active
interface Port-channel3
description CORE (2x10G)
switchport mode trunk
switchport trunk allowed vlan 30,99# PROD-SW — CRS326-24S+2Q+: IGMP snooping and a querier on the bridge
/interface bridge add name=bridge vlan-filtering=no igmp-snooping=yes multicast-querier=yes
:for i from=1 to=14 do={ /interface bridge port add bridge=bridge interface=("sfp-sfpplus" . $i) pvid=30 }
/interface bonding add name=bond-core slaves=sfp-sfpplus23,sfp-sfpplus24 mode=802.3ad
/interface bridge port add bridge=bridge interface=bond-core frame-types=admit-only-vlan-tagged
/interface bridge vlan add bridge=bridge vlan-ids=30,99 tagged=bond-core
/interface bridge set bridge vlan-filtering=yesThe production team uses NDI to move video between machines: each observer's game view, the casters' cameras, replay outputs and graphics all become network sources. A full-bandwidth 1080p60 NDI stream is about 125–150 Mb/s, and a vision mixer may pull a dozen at once, which is why the gallery is 10G and the uplink is 2×10G. Two settings keep it stable:
show ip igmp snooping groups lists only the ports that joined it.08 · Step 4 of 11
Eight high-density APs for the bowl and concourse, and wired desks for the press.
▲ Show step 4 in the interactive topology · see what this step adds, and click any device for its config
hostname FOH-SW interface range GigabitEthernet1/0/1 - 8 description ARENA APs (FlexConnect local switching) switchport mode trunk switchport trunk native vlan 99 switchport trunk allowed vlan 40,50,99 spanning-tree portfast trunk interface range GigabitEthernet1/0/9 - 16 description PRESS desks switchport mode access switchport access vlan 40 spanning-tree portfast spanning-tree bpduguard enable interface TenGigabitEthernet1/1/1 description CORE switchport mode trunk switchport trunk allowed vlan 40,50,99
The APs are mounted around the seating bowl and concourse, pointing at the crowd, with 20 MHz channels and a per-client rate limit of 1 Mb/s on the public SSID (set on the wireless controller). No AP is mounted on or near the stage: players use wired peripherals only (a common tournament rule, because the 2.4 GHz band in a full arena is unusable), and keeping APs away from the stage avoids anyone suggesting that the Wi-Fi had anything to do with a player's game.
09 · Step 5 of 11
One C9300 joins the four zones, routes everything except the stage pod and the public, and hands the internet to the edge.
▲ Show step 5 in the interactive topology · see what this step adds, and click any device for its config
hostname CORE
ip routing
interface TenGigabitEthernet1/1/2
description STAGE-SW (routed)
no switchport
ip address 10.90.255.1 255.255.255.252
interface TenGigabitEthernet1/1/3
description BOOTCAMP-SW
switchport mode trunk
switchport trunk allowed vlan 11,99
interface range TenGigabitEthernet1/1/4 - 5
channel-group 3 mode active
interface Port-channel3
description PROD-SW
switchport mode trunk
switchport trunk allowed vlan 30,99
interface TenGigabitEthernet1/1/6
description FOH-SW
switchport mode trunk
switchport trunk allowed vlan 40,50,99
interface TenGigabitEthernet1/1/1
description EDGE (transit + public)
switchport mode trunk
switchport trunk allowed vlan 50,900
!
interface Vlan11
ip address 10.90.11.1 255.255.255.0
interface Vlan30
ip address 10.90.30.1 255.255.255.0
interface Vlan40
ip address 10.90.40.1 255.255.255.0
interface Vlan99
ip address 10.90.99.1 255.255.255.0
interface Vlan900
ip address 10.90.254.2 255.255.255.248
! no "interface Vlan50": the public is routed by the EDGE only
!
ip route 10.90.10.0 255.255.255.0 10.90.255.2
ip route 10.90.15.0 255.255.255.0 10.90.255.2
ip route 10.90.20.0 255.255.255.0 10.90.255.2
ip route 0.0.0.0 0.0.0.0 10.90.254.1Static routes are enough for a network with one door per zone and no redundant paths, and they're one less thing to go wrong on match day. The public VLAN passes through the core at Layer 2 to the edge, the same pattern as the law firm and the supermarket.
show ip route: the three stage subnets via 10.90.255.2, default via 10.90.254.1 (the edge arrives in step 8).10 · Step 6 of 11
Players reach the match servers and an allowlist. Observers reach a delayed feed. The pod's one door lets in nothing else.
server:
interface: 10.90.20.53
access-control: 10.90.10.0/24 allow
local-zone: "." always_nxdomain
local-zone: "login.publisher.example." transparent
local-zone: "matchmaking.publisher.example." transparent
local-zone: "anticheat.publisher.example." transparent
local-zone: "cdn.publisher.example." transparent
forward-zone:
name: "."
forward-addr: 9.9.9.9
forward-addr: 149.112.112.112ip access-list extended V10-IN remark PLAYERS: match servers, the allowlist resolver, HTTPS out 10 permit udp 10.90.10.0 0.0.0.255 10.90.15.0 0.0.0.255 range 27015 27020 20 permit udp 10.90.10.0 0.0.0.255 host 10.90.20.53 eq domain 30 permit tcp 10.90.10.0 0.0.0.255 host 10.90.20.53 eq domain 40 permit tcp 10.90.10.0 0.0.0.255 10.90.20.0 0.0.0.255 established 50 deny ip any 10.0.0.0 0.255.255.255 log 60 deny ip any 172.16.0.0 0.15.255.255 70 deny ip any 192.168.0.0 0.0.255.255 80 permit tcp 10.90.10.0 0.0.0.255 any eq 443 90 deny ip any any log ! ip access-list extended V15-IN remark MATCH SERVERS: answer players and observers, report results 10 permit udp 10.90.15.0 0.0.0.255 range 27015 27020 10.90.10.0 0.0.0.255 20 permit udp 10.90.15.0 0.0.0.255 eq 27020 10.90.30.0 0.0.0.255 30 permit tcp 10.90.15.0 0.0.0.255 10.90.20.0 0.0.0.255 established 40 deny ip any 10.0.0.0 0.255.255.255 log 50 permit tcp 10.90.15.0 0.0.0.255 any eq 443 60 deny ip any any log ! ip access-list extended UPLINK-IN remark The pod's only door: delayed spectator feed in, replies in, nothing else 10 permit udp 10.90.30.0 0.0.0.255 10.90.15.0 0.0.0.255 eq 27020 20 permit tcp any 10.90.10.0 0.0.0.255 established 30 permit tcp any 10.90.15.0 0.0.0.255 established 40 permit tcp any 10.90.20.0 0.0.0.255 established 50 permit udp any eq domain host 10.90.20.53 60 deny ip any any log ! interface Vlan10 ip access-group V10-IN in interface Vlan15 ip access-group V15-IN in interface TenGigabitEthernet1/1/1 ip access-group UPLINK-IN in
# Stage pod on MikroTik: a CRS312 switches the pod, a small CCR2004 routes it with a
# stateful firewall (software routing, but identical for both teams; measure it)
/ip firewall filter
add chain=forward action=accept connection-state=established,related,untracked
add chain=forward action=drop connection-state=invalid
add chain=forward action=accept in-interface=v10-players out-interface=v15-servers protocol=udp dst-port=27015-27020
add chain=forward action=accept in-interface=v10-players dst-address=10.90.20.53 protocol=udp dst-port=53
add chain=forward action=drop in-interface=v10-players protocol=udp dst-port=53,853 log=yes log-prefix=DNS-BYPASS
add chain=forward action=accept in-interface=v10-players out-interface=uplink protocol=tcp dst-port=443
add chain=forward action=accept in-interface=uplink src-address=10.90.30.0/24 out-interface=v15-servers \
protocol=udp dst-port=27020 comment="observers: delayed spectator feed only"
add chain=forward action=accept in-interface=v20-ops
add chain=forward action=drop log=yes log-prefix=POD-DROPThe ports are an example: 27015 for the game and 27020 for the delayed spectator feed are the defaults for Source-engine titles. Every publisher's tournament guide lists its own, and each one becomes a named, commented line. The ops VLAN (referee, admin consoles) has no inbound ACL; it can reach players and servers for administration, and the players' ACL only lets them answer it.
Line 80 lets players open HTTPS to any address, which looks like the opposite of an allowlist. But a player PC only learns addresses through DNS-ALLOW, which refuses every name except the publisher's, and line 50 blocks every other resolver inside the building. Two gaps remain, and both are closed on the PC, not the network: encrypted DNS (DoH) to a public resolver, and connecting to an IP address typed by hand. The tournament image disables DoH by policy, players have no admin rights, and the referee's checklist includes a quick look at each seat's browser before every match.
nslookup twitch.tv returns NXDOMAIN; nslookup example.com 8.8.8.8 times out.11 · Step 7 of 11
Every packet on the stage is copied to a disk. A lag complaint becomes a measurement.
▲ Show step 7 in the interactive topology · see what this step adds, and click any device for its config
monitor session 1 source interface TenGigabitEthernet1/0/1 - 12 both monitor session 1 destination interface TenGigabitEthernet1/0/24
# CRS3xx port mirroring: every player and server port copied to the capture box on ether24
/interface ethernet switch port set ether1,ether2,ether3,ether4,ether5,ether6,ether7,ether8,ether9,ether10,ether11,ether12 \
mirror-ingress=yes mirror-egress=yes
/interface ethernet switch set switch1 mirror-ingress-target=ether24 mirror-egress-target=ether24
# property names have changed across RouterOS 7 releases: check /interface ethernet switch printdumpcap -i cap0 -b duration:600 -b files:288 -w /data/stage.pcapng
The capture box has two network ports: cap0 on Te1/0/24 receives the SPAN copy (a SPAN destination port doesn't carry normal traffic), and a second port on Te1/0/14 in the ops VLAN is how the referee reaches it. A full match generates a few GB of game traffic; 48 hours of 10-minute files fits comfortably on a 2 TB disk. The files are deleted after the event's dispute window closes, and that retention is stated in the tournament rules players sign.
show monitor session 1: sources Te1/0/1–12, destination Te1/0/24.12 · Step 8 of 11
ISP A carries the event; ISP B belongs to encoder 1 and catches the platform if A fails. The public never touches B.
▲ Show step 8 in the interactive topology · see what this step adds, and click any device for its config
interface GigabitEthernet0/0/2.900 encapsulation dot1Q 900 ip address 10.90.254.1 255.255.255.248 ip nat inside zone-member security INSIDE ip policy route-map PBR-IN interface GigabitEthernet0/0/2.50 encapsulation dot1Q 50 ip address 10.90.48.1 255.255.248.0 ip nat inside zone-member security PUBLIC interface GigabitEthernet0/0/0 description ISP A ip address 203.0.113.10 255.255.255.248 ip nat outside zone-member security OUTSIDE-A interface GigabitEthernet0/0/1 description ISP B ip address 198.51.100.10 255.255.255.248 ip nat outside zone-member security OUTSIDE-B ! ip sla 1 icmp-echo 1.1.1.1 source-interface GigabitEthernet0/0/0 frequency 5 ip sla schedule 1 life forever start-time now track 1 ip sla 1 reachability delay down 10 up 60 ip sla 2 icmp-echo 9.9.9.9 source-interface GigabitEthernet0/0/1 frequency 5 ip sla schedule 2 life forever start-time now track 2 ip sla 2 reachability ip route 1.1.1.1 255.255.255.255 203.0.113.9 ! each probe pinned to its own ISP ip route 1.1.1.1 255.255.255.255 Null0 250 ip route 9.9.9.9 255.255.255.255 198.51.100.9 ip route 9.9.9.9 255.255.255.255 Null0 250 ip route 0.0.0.0 0.0.0.0 203.0.113.9 track 1 ip route 0.0.0.0 0.0.0.0 198.51.100.9 250 ip route 10.90.0.0 255.255.0.0 10.90.254.2 ! ! encoder 1 always leaves via ISP B while ISP B is healthy ip access-list extended ENC1 permit ip host 10.90.30.21 any route-map PBR-IN permit 10 match ip address ENC1 set ip next-hop verify-availability 198.51.100.9 1 track 2 ! route-map NAT-A permit 10 match interface GigabitEthernet0/0/0 route-map NAT-B permit 10 match interface GigabitEthernet0/0/1 ip nat inside source route-map NAT-A interface GigabitEthernet0/0/0 overload ip nat inside source route-map NAT-B interface GigabitEthernet0/0/1 overload
zone security INSIDE
zone security PUBLIC
zone security OUTSIDE-A
zone security OUTSIDE-B
class-map type inspect match-any CM-ANY
match protocol tcp
match protocol udp
match protocol icmp
policy-map type inspect PM-OUT
class type inspect CM-ANY
inspect
class class-default
drop log
zone-pair security ZP-IN-A source INSIDE destination OUTSIDE-A
service-policy type inspect PM-OUT
zone-pair security ZP-IN-B source INSIDE destination OUTSIDE-B
service-policy type inspect PM-OUT
zone-pair security ZP-PUB-A source PUBLIC destination OUTSIDE-A
service-policy type inspect PM-OUT
! no PUBLIC → OUTSIDE-B pair: when ISP A fails, spectators simply have no internet# EDGE (CCR2116) — interface lists for zones, routing tables for "which ISP" /routing table add name=isp-b fib /routing table add name=isp-a-only fib /ip route add dst-address=0.0.0.0/0 gateway=203.0.113.9 distance=1 routing-table=isp-a-only add dst-address=0.0.0.0/0 gateway=198.51.100.9 distance=1 routing-table=isp-b /routing rule add dst-address=10.90.0.0/16 action=lookup-only-in-table table=main add src-address=10.90.30.21/32 action=lookup table=isp-b comment="encoder 1 on ISP B" add src-address=10.90.48.0/21 action=lookup-only-in-table table=isp-a-only comment="public: ISP A or nothing"
Putting each ISP in its own zone gives the "who may use the backup" rule for free, the same idea as the supermarket's tunnel-only LTE zone. A self-zone policy for the probes isn't needed here, because nothing on the WAN needs to reach the edge itself. If you add one later, remember the echo-reply line from the law firm. The route-map NAT per interface is the law firm's dual-WAN NAT lesson again.
show route-map PBR-IN: encoder 1's packets counted; a traceroute from encoder 1 leaves via ISP B.13 · Step 9 of 11
Two encoders, two ISPs, one cloud ingest that always has a healthy copy.
Both encoders take the same program output from the vision mixer and send it with SRT (a protocol built for live video over the public internet: it retransmits lost packets within a fixed latency budget) to two inputs of a cloud production service. Encoder 1 leaves via ISP B because of the policy route; encoder 2 leaves via ISP A by normal routing. The cloud service watches both and forwards one to the streaming platforms. If an ISP, an encoder or a cable fails, it switches within a second. The production network's ACL on the core allows the encoders out to the cloud ingest and nothing else.
14 · Step 10 of 11
The platform, the referee and encoder 2 first; press and spectators share the rest.
ip access-list extended CRIT permit ip 10.90.10.0 0.0.0.255 any permit ip 10.90.15.0 0.0.0.255 any permit ip 10.90.20.0 0.0.0.255 any permit ip host 10.90.30.22 any class-map match-any CRIT match access-group name CRIT policy-map MARK-IN class CRIT set qos-group 1 interface GigabitEthernet0/0/2.900 service-policy input MARK-IN ! class-map match-any CRIT-Q match qos-group 1 policy-map WAN-A-CHILD class CRIT-Q bandwidth remaining percent 60 class class-default fair-queue policy-map WAN-A class class-default shape average 475000000 service-policy WAN-A-CHILD interface GigabitEthernet0/0/0 service-policy output WAN-A
# EDGE — on RouterOS the gotcha doesn't exist: mangle in the forward chain # runs before srcnat, so inside addresses are still visible when marking /ip firewall address-list add list=CRIT address=10.90.10.0/24 add list=CRIT address=10.90.15.0/24 add list=CRIT address=10.90.20.0/24 add list=CRIT address=10.90.30.22 /ip firewall mangle add chain=forward action=mark-packet new-packet-mark=crit out-interface=ether1 src-address-list=CRIT passthrough=no add chain=forward action=mark-packet new-packet-mark=rest out-interface=ether1 passthrough=no /queue type add name=fq kind=fq-codel /queue tree add name=ISP-A parent=ether1 max-limit=475M add name=crit parent=ISP-A packet-mark=crit priority=1 limit-at=285M max-limit=475M queue=fq add name=rest parent=ISP-A packet-mark=rest priority=8 max-limit=475M queue=fq
By the time a packet reaches the output policy on Gi0/0/0, NAT has already rewritten its source to the ISP A address, so an ACL matching 10.90.10.0/24 there would never match anything. The fix is to classify where the inside addresses are still visible, on the LAN subinterface's input policy, and carry the decision across the router as a qos-group (a label that exists only inside this router). The output policy then queues by qos-group. The 1 Mb/s per spectator is enforced at the APs; this policy makes sure that even 1,500 of them together can't squeeze the critical class below 60% of the line.
show policy-map interface Gi0/0/0 shows drops only in class-default.15 · Step 11 of 11
A change freeze you can roll back, monitoring the director can read, and nothing improvised.
archive path flash:matchday log config logging enable notify syslog contenttype plaintext hidekeys ! the night before each match day, after the scrim passes: copy running-config flash:matchday-baseline.cfg ! if a change on match day goes wrong: configure replace flash:matchday-baseline.cfg list
# every device — baseline the night before, roll back by restoring it /system backup save name=matchday-baseline dont-encrypt=no password=******** /export file=matchday-baseline # risky change on match day: do it in Safe Mode (Ctrl+X), which undoes itself if you lose the session # full rollback: /system backup load name=matchday-baseline.backup (reboots the device)
The tournament director approves any change on match days, the network lead makes it, and every command is logged with the user who typed it. configure replace puts a device back to the baseline in seconds, without a reload. In the NOC corner of the production gallery, one screen shows the IP SLA probes for both ISPs, the SRT health of both encoders, STAGE-SW's port counters and errors, and the AP client counts. If any of those changes during a match, the network lead sees it first. Management access is limited to VLAN 99 and the ops VLAN (see hardening).
configure replace: the device returns to the baseline, and the syslog shows both the change and the rollback with usernames.16
The day before doors open, two teams play a full match on stage with the whole production running. Every drill happens during that match.
| Drill (requirement) | What must happen |
|---|---|
| Fair paths (R1) | Latency from every seat to the match server measured with a high-resolution tool: all ten within a few microseconds; all ports at the same speed. |
| No ghosting (R2) | On a player PC, any stream or video site fails to resolve; DNS to outside resolvers times out. |
| Delayed spectating (R3) | Observers see the match on the spectator delay; nothing else from production reaches the pod. |
| Dispute drill (R4) | The referee extracts and graphs one seat's traffic for a chosen two-minute window. |
| Broadcast resilience (R5) | Unplug ISP B, then ISP A (one at a time): the cloud output never blinks. |
| Production load (R6) | All NDI sources live at full bandwidth for the whole match, no dropped frames at the mixer. |
| Crowd (R7) | The public VLAN loaded to its limit: player login and the match unaffected. |
| Freeze and rollback (R8) | Baselines saved; one rollback rehearsed. |
17
What the network can't rule out, and what covers it.
18
Indicative EU street prices, late 2026, excluding VAT. Often rented for the event; listed here at purchase price.
| Item | Indicative (EUR, ex VAT) |
|---|---|
| EDGE · C8300-1N1S-6T | 3,000 – 4,500 |
| CORE · C9300-48T + 8×10G module | 5,000 – 7,000 incl. DNA |
| STAGE-SW + PROD-SW · 2× C9300-24UX | 9,000 – 13,000 incl. DNA |
| BOOTCAMP-SW · C9300-48P | 4,500 – 6,000 incl. DNA |
| FOH-SW · C9200L-24P + 8 Wi-Fi 6E APs | 6,000 – 8,500 |
| Capture box (2 TB, two NICs) + DNS-ALLOW VM host | 1,500 – 2,500 |
| Optics, DACs, cable (incl. matched stage cables) | 800 – 1,500 |
| Network total | ≈ 30,000 – 43,000 to buy; typically a fraction of that to rent for a weekend |
19
The pod, the core and every ACL run in Packet Tracer. The edge, capture and NDI need real gear or CML.
| This post | In Packet Tracer |
|---|---|
| STAGE-SW, CORE | 3650-24PS with ip routing: routed uplink, SVIs, every ACL in step 6, static routes. Server-PT boxes stand in for the match servers and DNS-ALLOW. |
| BOOTCAMP / PROD / FOH | 2960 or 3650 switches with the same VLANs and trunks. IGMP snooping exists, but NDI obviously doesn't. |
| SPAN | Supported on the switches; a Sniffer device on the destination port shows the copied traffic. |
| EDGE | ISR4331 for NAT and static routes. PBR with tracking, ZBF with four zones and hierarchical QoS need CML or EVE-NG with a Cat8000v. |
Appendix
Same arena, same zones and rules, at a fraction of the cost. The MikroTik tabs on the config blocks above show the key steps side by side; this appendix covers what changes underneath.
| Role | This post → MikroTik |
|---|---|
| Stage pod | C9300-24UX (L3) → CRS312-4C+8XG (switching) + CCR2004-1G-12S+2XS (pod routing and firewall) |
| BOOTCAMP-SW | C9300-48P → CRS354-48G-4S+2Q+ |
| PROD-SW | C9300-24UX → CRS326-24S+2Q+ (10G SFP+ to every production machine) |
| FOH-SW | C9200L-24P → CRS328-24P-4S+ |
| CORE + EDGE | C9300-48T + C8300 → CRS326-24S+2Q+ (Layer 2) + CCR2116-12G-4S+ (all routing, both ISPs) |
| Indicative total | ≈ 30,000 – 43,000 → ≈ 5,000 – 7,500 EUR ex VAT |
| Feature | This post → MikroTik |
|---|---|
| Stage pod routing | C9300 SVIs in hardware → a small CCR routing the pod in software |
| Pod ACLs | stateless ACLs with established → stateful forward chain |
| SPAN | monitor session → switch-chip port mirroring to one target port |
| IGMP snooping + querier | ip igmp snooping querier → bridge igmp-snooping + multicast-querier |
| ISP per zone | PBR + zone pairs → routing tables + routing rules |
| QoS before NAT | qos-group marked on ingress → mangle in forward (already before srcnat) |
| Change freeze | archive + configure replace → backups, /export and Safe Mode |
The stage pod is the hard part. A Catalyst routes the pod in its switching hardware with identical, tiny latency for every port. On MikroTik the pod is routed by a small CCR in software. That's still well under a tenth of a millisecond and the same for both teams, but it's exactly the kind of claim the fairness rules say must be measured, not assumed. Rollback is coarser: there's no configure replace, so match-day changes rely on Safe Mode and a full backup restore.
For a one-off community tournament, MikroTik is a sensible choice. For a broadcast final with prize money, the hardware-routed pod and atomic rollback are worth the Cisco price.
Takeaways
This is part 8 of the Build series. Earlier: the law firm, the gaming center, the coffee shop, the supermarket, the medical clinic, the holiday villa, the festival.
I design competition networks with fair paths, sealed stage pods and evidence for disputes, alongside production networks that keep the broadcast on air.
Book a Discovery Call →