STP/RSTP Convergence Simulator

body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 0; } .calc-container { max-width: 900px; margin: 20px auto; padding: 20px; } /* ── Header ── */ .calc-header { margin-bottom: 30px; padding: 25px; background: linear-gradient(135deg, #2196F3 0%, #1976D2 100%); border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); color: white; } .calc-header h2 { margin-top: 0; color: white; font-size: 28px; margin-bottom: 10px; } .calc-header p { margin: 10px 0 20px 0; opacity: 0.95; font-size: 15px; } /* ── Form controls inside header ── */ .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 20px; } .form-group { display: flex; flex-direction: column; gap: 8px; } .form-group label { font-weight: 600; font-size: 14px; color: white; } .form-group input, .form-group select { padding: 12px; font-size: 15px; border: 2px solid rgba(255,255,255,0.3); border-radius: 6px; background: rgba(255,255,255,0.95); transition: all 0.3s ease; font-family: 'Courier New', monospace; } .form-group input:focus, .form-group select:focus { outline: none; border-color: #4CAF50; background: white; box-shadow: 0 0 0 3px rgba(76,175,80,0.15); } .form-group select { cursor: pointer; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } /* ── Buttons ── */ .btn { padding: 12px 24px; font-size: 15px; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } .btn-primary { background: #4CAF50; color: white; } .btn-primary:hover { background: #45a049; transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0,0,0,0.25); } .btn-primary:active { background: #3d8b40; transform: translateY(0); } .btn-secondary { background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.4); } .btn-secondary:hover { background: rgba(255,255,255,0.3); transform: translateY(-1px); } .btn-danger { background: #f44336; color: white; } .btn-danger:hover { background: #d32f2f; transform: translateY(-1px); } .btn-sm { padding: 6px 14px; font-size: 13px; } .submit-btn { padding: 14px 35px; font-size: 16px; background: #4CAF50; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2); margin-top: 15px; width: 100%; } .submit-btn:hover { background: #45a049; transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0,0,0,0.3); } .submit-btn:active { background: #3d8b40; transform: translateY(0); } /* ── Result sections ── */ .result-section { background: white; border: 1px solid #e0e0e0; border-radius: 8px; margin-top: 20px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.05); transition: all 0.3s ease; display: none; } .result-section.show { display: block; } .result-section:hover { box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .section-header { background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%); color: white; padding: 15px 20px; } .section-header h3 { margin: 0; font-size: 18px; display: flex; align-items: center; gap: 10px; } .section-header.blue { background: linear-gradient(135deg, #2196F3 0%, #1976D2 100%); } .section-header.orange { background: linear-gradient(135deg, #FF9800 0%, #F57C00 100%); } .section-header.purple { background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); } .section-content { padding: 20px; background: #fafafa; } .data-row { display: flex; margin: 10px 0; padding: 10px; background: white; border-radius: 4px; border-left: 3px solid #4CAF50; align-items: flex-start; } .data-label { font-weight: bold; color: #555; min-width: 200px; flex-shrink: 0; font-size: 14px; padding-top: 1px; } .data-value { color: #333; font-family: 'Courier New', monospace; word-break: break-word; font-size: 15px; } .data-value.highlight { color: #1976D2; font-weight: bold; font-size: 18px; } /* ── Help text ── */ .help-text { margin-top: 15px; font-size: 14px; color: rgba(255,255,255,0.9); background: rgba(0,0,0,0.1); padding: 10px 15px; border-radius: 4px; } .help-text strong { color: white; } /* ── Topology canvas area ── */ #cy-container { width: 100%; height: 380px; background: #1a2332; border-radius: 8px; border: 2px solid #2d3d52; position: relative; overflow: hidden; } #cy { width: 100%; height: 100%; } /* ── Switch list ── */ .switch-list, .link-list { list-style: none; margin: 0; padding: 0; } .switch-item, .link-item { display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: white; border-radius: 5px; margin-bottom: 6px; border-left: 4px solid #2196F3; font-size: 14px; flex-wrap: wrap; } .switch-item .sw-id { font-family: 'Courier New', monospace; font-weight: bold; color: #1976D2; min-width: 40px; } .switch-item .sw-name { flex: 1; font-weight: 600; } .switch-item .sw-priority, .switch-item .sw-mac { font-family: 'Courier New', monospace; font-size: 13px; color: #666; } .link-item { border-left-color: #FF9800; } .link-item .lk-label { flex: 1; font-family: 'Courier New', monospace; font-size: 13px; } .tag { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: bold; } .tag-root { background: #FFF3CD; color: #856404; } .tag-fwd { background: #D4EDDA; color: #155724; } .tag-blk { background: #F8D7DA; color: #721C24; } .tag-disc { background: #D1ECF1; color: #0C5460; } .tag-lrn { background: #CCE5FF; color: #004085; } .tag-edge { background: #E2D9F3; color: #491F8A; } /* ── Port state table ── */ .port-table { width: 100%; border-collapse: collapse; font-size: 14px; margin-top: 8px; } .port-table th { background: #E3F2FD; color: #1565C0; padding: 8px 12px; text-align: left; font-weight: 600; border-bottom: 2px solid #BBDEFB; } .port-table td { padding: 7px 12px; border-bottom: 1px solid #f0f0f0; font-family: 'Courier New', monospace; font-size: 13px; } .port-table tr:last-child td { border-bottom: none; } .port-table tr:nth-child(even) td { background: #f8f9fa; } /* ── Timeline ── */ .timeline { position: relative; padding-left: 28px; } .timeline::before { content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 2px; background: #BBDEFB; } .timeline-event { position: relative; margin-bottom: 12px; background: white; border-radius: 6px; padding: 10px 14px; border: 1px solid #e8e8e8; font-size: 13px; } .timeline-event::before { content: ''; position: absolute; left: -24px; top: 12px; width: 10px; height: 10px; border-radius: 50%; background: #2196F3; border: 2px solid white; box-shadow: 0 0 0 2px #2196F3; } .timeline-event.root-election::before { background: #FFC107; box-shadow: 0 0 0 2px #FFC107; } .timeline-event.port-change::before { background: #4CAF50; box-shadow: 0 0 0 2px #4CAF50; } .timeline-event.port-blocked::before { background: #f44336; box-shadow: 0 0 0 2px #f44336; } .timeline-event.convergence::before { background: #9C27B0; box-shadow: 0 0 0 2px #9C27B0; } .timeline-event .te-time { font-weight: bold; color: #1976D2; font-family: 'Courier New', monospace; margin-right: 8px; } .timeline-event .te-desc { color: #333; } /* ── BPDU Inspector ── */ .bpdu-panel { background: #0d1117; border-radius: 6px; padding: 15px; font-family: 'Courier New', monospace; font-size: 13px; color: #79c0ff; max-height: 300px; overflow-y: auto; } .bpdu-row { display: flex; gap: 8px; margin-bottom: 3px; line-height: 1.5; } .bpdu-field { color: #d2a8ff; min-width: 180px; flex-shrink: 0; } .bpdu-val { color: #a5f3fc; } .bpdu-val.root { color: #fbbf24; } .bpdu-val.bridge { color: #86efac; } /* ── Scenario selector ── */ .scenario-bar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 10px; } .scenario-bar label { font-weight: 600; font-size: 14px; color: white; } .scenario-bar select { padding: 8px 12px; border: 2px solid rgba(255,255,255,0.3); border-radius: 6px; background: rgba(255,255,255,0.95); font-size: 14px; cursor: pointer; flex: 1; min-width: 200px; } /* ── Legend ── */ .legend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; font-size: 13px; } .legend-item { display: flex; align-items: center; gap: 5px; } .legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; } /* ── Inline error / info messages ── */ .msg { padding: 10px 14px; border-radius: 6px; font-size: 14px; margin-top: 8px; } .msg-error { background: #FFEBEE; color: #C62828; border-left: 4px solid #f44336; } .msg-info { background: #E3F2FD; color: #1565C0; border-left: 4px solid #2196F3; } .msg-success { background: #E8F5E9; color: #1B5E20; border-left: 4px solid #4CAF50; } /* ── STP concept panel ── */ .concept-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } .concept-card { background: white; border-radius: 6px; padding: 14px; border-top: 3px solid #2196F3; font-size: 13px; } .concept-card h4 { margin: 0 0 6px 0; color: #1976D2; font-size: 14px; } .concept-card p { margin: 0; color: #555; line-height: 1.5; } .concept-card.rstp { border-top-color: #9C27B0; } .concept-card.rstp h4 { color: #7B1FA2; } /* ── Mode toggle ── */ .mode-toggle { display: flex; gap: 0; margin-top: 15px; background: rgba(0,0,0,0.15); border-radius: 6px; padding: 4px; } .mode-btn { flex: 1; padding: 8px 16px; border: none; background: transparent; color: rgba(255,255,255,0.7); cursor: pointer; border-radius: 4px; font-size: 14px; font-weight: 600; transition: all 0.2s ease; } .mode-btn.active { background: white; color: #1976D2; box-shadow: 0 1px 3px rgba(0,0,0,0.2); } /* ── Pulse animation for root bridge ── */ @keyframes rootPulse { 0% { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(255, 193, 7, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0); } } @keyframes fadeInUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } .fade-in-up { animation: fadeInUp 0.35s ease both; } /* ── Responsive ── */ @media (max-width: 768px) { .form-grid { grid-template-columns: 1fr; } .data-row { flex-direction: column; } .data-label { margin-bottom: 4px; min-width: auto; } .concept-grid { grid-template-columns: 1fr; } #cy-container { height: 280px; } .port-table { font-size: 12px; } .port-table th, .port-table td { padding: 6px 8px; } .mode-btn { padding: 8px 8px; font-size: 13px; } .scenario-bar { flex-direction: column; align-items: stretch; } .scenario-bar label { display: block; } } @media (max-width: 480px) { .calc-header { padding: 18px; } .calc-header h2 { font-size: 22px; } .switch-item, .link-item { flex-wrap: wrap; } }
═════════════════════════════ ══════════════════════════════ KOP / CONFIGURATIE ═════════════════════════════ ══════════════════════════════

STP / RSTP-convergentiesimulator

Bouw een netwerktopologie, voer STP of RSTP uit en inspecteer rootbridge-verkiezing, poortstatussen en convergentietijdlijn.

Keuzeschakelaar protocolmodus
Schakelformulier toevoegen
Schakelaar toevoegen
Linkformulier toevoegen
Koppeling toevoegen
Mislukkingsscenario
Tip:Voeg minimaal 3 switches toe met redundante links (driehoek of ring) om geblokkeerde poorten te zien. Laad een preset met de onderstaande knop of bouw uw eigen topologie.
Vooraf ingestelde topologieën
/.calc-header ═════════════════════════════ ══════════════════════════════ HUIDIGE TOPOLOGIELIJST ═════════════════════════════ ══════════════════════════════

Huidige topologie

Schakelaars
  • Er zijn nog geen schakelaars toegevoegd.
Koppelingen
═════════════════════════════ ══════════════════════════════ TOPOLOGIE VISUALISATIE ═════════════════════════════ ══════════════════════════════

Topologiediagram

Legende
Wortelbrug
Doorstuurpoort
Poort blokkeren/weggooien
Root-poort
Aangewezen haven
Onderbroken lijn = geblokkeerde link
═════════════════════════════ ══════════════════════════════ WORTELBRUG VERKIEZING ═════════════════════════════ ══════════════════════════════

Rootbridge-verkiezing

═════════════════════════════ ══════════════════════════════ HAVENSTATEN ═════════════════════════════ ══════════════════════════════

Havenstaten

═════════════════════════════ ══════════════════════════════ BPDU-INSPECTEUR ═════════════════════════════ ══════════════════════════════

BPDU-inspecteur

═════════════════════════════ ══════════════════════════════ CONVERGENTIE TIJDLIJN ═════════════════════════════ ══════════════════════════════

Convergentie tijdlijn

═════════════════════════════ ══════════════════════════════ STP-CONCEPTEN ═════════════════════════════ ══════════════════════════════

STP / RSTP-concepten

Rootbridge-verkiezing

De schakelaar met de laagste Bridge-ID wint. Bridge-ID = Prioriteit (standaard 32768) + MAC-adres. Banden op prioriteit gaan naar een numeriek lagere MAC. Slechts één rootbridge per VLAN.

Root-poort

Elke niet-rootswitch kiest één rootpoort: de poort met de laagste cumulatieve padkosten naar de rootbridge. De banden worden verbroken door de Bridge-ID van de buurman en vervolgens door de poort-ID.

Aangewezen haven

Elk netwerksegment heeft precies één aangewezen poort: de poort die het beste (laagste kosten) pad naar de root biedt. Alle poorten op de rootbridge zijn aangewezen.

Geblokkeerde/verwijderende poorten

Elke poort die noch een rootpoort, noch een aangewezen poort is, wordt geblokkeerd (STP) of verwijderd (RSTP). Deze breken Layer-2-lussen terwijl een lusvrije topologie behouden blijft.

RSTP (802.1w) Edge-poorten

RSTP-randpoorten maken verbinding met eindhosts, niet met andere switches. Ze schakelen onmiddellijk over naar Doorsturen (geen luister-/leervertraging), wat overeenkomt met de PortFast-functie van STP.

RSTP-convergentiesnelheid

STP-convergentie duurt 30-50 seconden (15 seconden luisteren + 15 seconden leren per poort). RSTP maakt gebruik van een voorstel/overeenkomst-handshake, die in minder dan 2 seconden per hop samenkomt.

Padkosten (IEEE 802.1D)

10 Gbps = 2, 1 Gbps = 4, 100 Mbps = 19, 10 Mbps = 100, 1,5 Mbps = 1000. Lagere kosten = voorkeurspad. Rootbridge adverteert met kosten 0; elke hop voegt zijn havenkosten toe.

BPDU (Bridge Protocol-gegevenseenheid)

BPDU's bevatten: Root Bridge ID, Root Path Cost, Sender Bridge ID, Port ID en timers. Rootbridge genereert elke Hello Time (2s) BPDU's. Andere bruggen geven ze door via aangewezen havens.

/.calc-container Cytoscape.js CDN