BGP Network Design & Simulation Tool
#bgp-app {
display: grid;
grid-template-columns: 280px 1fr;
grid-template-rows: 1fr 300px;
height: 85vh;
gap: 2px;
background: #2d2d2d;
margin: 0;
}
/* Sidebar */
#bgp-sidebar {
grid-row: 1 / 3;
background: #252526;
padding: 15px;
overflow-y: auto;
border-right: 2px solid #3e3e42;
}
#bgp-sidebar h2 {
color: #4fc3f7;
margin-bottom: 15px;
font-size: 18px;
border-bottom: 2px solid #4fc3f7;
padding-bottom: 5px;
}
.palette-section {
margin-bottom: 20px;
}
.palette-section h3 {
color: #81c784;
font-size: 14px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.palette-section h3 .add-btn {
background: #4fc3f7;
color: #000;
border: none;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
font-weight: bold;
}
.palette-section h3 .add-btn:hover {
background: #29b6f6;
}
.palette-item {
background: #3c3c3c;
padding: 12px;
margin-bottom: 8px;
border-radius: 6px;
cursor: grab;
border: 2px solid #555;
transition: all 0.2s;
text-align: center;
user-select: none;
}
.palette-item:active {
cursor: grabbing;
}
.palette-item:hover {
background: #4a4a4a;
border-color: #4fc3f7;
transform: translateX(5px);
box-shadow: 0 4px 8px rgba(79, 195, 247, 0.3);
}
.palette-item.router {
border-left: 4px solid #ff9800;
}
.palette-item.carrier {
border-left: 4px solid #9c27b0;
}
.policy-item {
background: #3c3c3c;
padding: 8px 10px;
margin-bottom: 6px;
border-radius: 4px;
border-left: 3px solid #4fc3f7;
cursor: pointer;
transition: all 0.2s;
display: flex;
justify-content: space-between;
align-items: center;
}
.policy-item:hover {
background: #4a4a4a;
transform: translateX(3px);
}
.policy-item-name {
font-size: 12px;
font-weight: bold;
color: #e0e0e0;
}
.policy-item-type {
font-size: 10px;
color: #9e9e9e;
}
.policy-item-actions {
display: flex;
gap: 5px;
}
.policy-item-actions button {
background: none;
border: none;
color: #9e9e9e;
cursor: pointer;
padding: 2px 5px;
font-size: 14px;
}
.policy-item-actions button:hover {
color: #4fc3f7;
}
.policy-item-actions .delete-btn:hover {
color: #e57373;
}
.controls {
margin-top: 20px;
}
.btn {
width: 100%;
padding: 12px;
margin-bottom: 10px;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
transition: all 0.2s;
font-size: 13px;
}
.btn-primary {
background: #4fc3f7;
color: #000;
}
.btn-primary:hover {
background: #29b6f6;
}
.btn-success {
background: #81c784;
color: #000;
}
.btn-success:hover {
background: #66bb6a;
}
.btn-success.active {
background: #66bb6a;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.3);
}
.btn-danger {
background: #e57373;
color: #000;
}
.btn-danger:hover {
background: #ef5350;
}
.btn-secondary {
background: #81c784;
color: #000;
}
.btn-secondary:hover {
background: #66bb6a;
}
.btn-small {
padding: 6px 12px;
font-size: 11px;
width: auto;
}
/* Canvas */
#canvas-container {
background: #1e1e1e;
position: relative;
background-image:
linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
background-size: 50px 50px;
border: 3px dashed rgba(79, 195, 247, 0.3);
transition: border-color 0.3s;
}
#canvas-container::before {
content: 'Drag routers and carriers here';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.2);
font-size: 24px;
font-weight: bold;
pointer-events: none;
z-index: 0;
}
#canvas-container.has-nodes::before {
display: none;
}
#canvas-container.peering-mode {
border-color: #81c784;
border-width: 4px;
}
#cy {
width: 100%;
height: 100%;
position: relative;
z-index: 1;
}
/* Looking Glass Panel */
#looking-glass {
background: #252526;
border-top: 2px solid #3e3e42;
display: flex;
flex-direction: column;
}
.tabs {
display: flex;
background: #2d2d2d;
border-bottom: 2px solid #3e3e42;
}
.tab {
padding: 12px 24px;
cursor: pointer;
border: none;
background: transparent;
color: #9e9e9e;
font-weight: bold;
transition: all 0.2s;
border-bottom: 3px solid transparent;
}
.tab.active {
color: #4fc3f7;
border-bottom-color: #4fc3f7;
}
.tab:hover {
background: #3e3e42;
}
.tab-content {
flex: 1;
overflow-y: auto;
padding: 15px;
display: none;
color: #e0e0e0;
}
.tab-content.active {
display: block;
}
.rib-entry {
background: #2d2d2d;
padding: 10px;
margin-bottom: 8px;
border-radius: 4px;
border-left: 4px solid #4fc3f7;
font-family: 'Courier New', monospace;
font-size: 12px;
transition: all 0.2s;
}
.rib-entry:hover {
background: #3a3a3a;
transform: translateX(5px);
box-shadow: 0 2px 8px rgba(0, 229, 255, 0.3);
}
.rib-entry.best {
border-left-color: #81c784;
background: #1b5e20;
}
.rib-entry.best:hover {
background: #2e7d32;
}
.rib-entry.modified {
border-left-color: #ff9800;
background: #4a2c00;
}
.rib-entry.modified:hover {
background: #663d00;
}
.rib-entry.originated {
border-left-color: #42a5f5;
background: #1a237e;
}
.rib-entry.originated:hover {
background: #283593;
}
.route-map-impact {
margin-top: 8px;
padding: 8px;
background: rgba(255, 152, 0, 0.1);
border-left: 2px solid #ff9800;
font-size: 11px;
font-style: italic;
}
.config-preview {
font-family: 'Courier New', monospace;
font-size: 12px;
line-height: 1.6;
white-space: pre-wrap;
background: #1e1e1e;
padding: 15px;
border-radius: 4px;
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
overflow-y: auto;
}
.modal.active {
display: flex;
align-items: flex-start;
justify-content: center;
padding: 20px;
}
.modal-content {
background: #2d2d2d;
padding: 30px;
border-radius: 8px;
max-width: 800px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
border: 2px solid #4fc3f7;
color: #e0e0e0;
margin: 20px auto;
}
.modal-content h3 {
color: #4fc3f7;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 10px;
}
.modal-section {
margin-bottom: 25px;
padding: 15px;
background: #1e1e1e;
border-radius: 6px;
border-left: 4px solid #4fc3f7;
}
.modal-section h4 {
color: #81c784;
margin-bottom: 15px;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 1px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-bottom: 15px;
}
.form-group {
margin-bottom: 15px;
}
.form-group.full-width {
grid-column: 1 / -1;
}
.form-group label {
display: block;
margin-bottom: 5px;
color: #81c784;
font-weight: bold;
font-size: 13px;
}
.form-group label .required {
color: #e57373;
}
.form-group label .optional {
color: #9e9e9e;
font-weight: normal;
font-size: 11px;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 10px;
background: #2d2d2d;
border: 1px solid #555;
border-radius: 4px;
color: #e0e0e0;
font-family: inherit;
font-size: 13px;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: #4fc3f7;
box-shadow: 0 0 0 2px rgba(79, 195, 247, 0.2);
}
.form-group input:disabled,
.form-group select:disabled {
background: #1a1a1a;
color: #666;
cursor: not-allowed;
}
.form-group .help-text {
font-size: 11px;
color: #9e9e9e;
margin-top: 4px;
font-style: italic;
}
.checkbox-group {
display: flex;
align-items: center;
gap: 8px;
padding: 10px;
background: #2d2d2d;
border-radius: 4px;
}
.checkbox-group input[type="checkbox"] {
width: auto;
cursor: pointer;
}
.checkbox-group label {
margin: 0;
cursor: pointer;
font-weight: normal;
}
/* Phase 3.1: Networks list styling */
.networks-list {
margin-bottom: 15px;
max-height: 200px;
overflow-y: auto;
background: #2d2d2d;
border-radius: 4px;
padding: 10px;
}
.network-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 10px;
background: #3e3e42;
border-radius: 4px;
margin-bottom: 6px;
border-left: 3px solid #81c784;
}
.network-item .network-prefix {
color: #81c784;
font-family: 'Courier New', monospace;
font-weight: bold;
}
.network-item .network-delete {
background: #e57373;
color: #000;
border: none;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
}
.network-item .network-delete:hover {
background: #ef5350;
}
.modal-actions {
display: flex;
gap: 10px;
margin-top: 25px;
padding-top: 20px;
border-top: 2px solid #3e3e42;
}
.collapsible-section {
margin-top: 15px;
}
.collapsible-header {
background: #3e3e42;
padding: 12px 15px;
border-radius: 4px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
transition: background 0.2s;
}
.collapsible-header:hover {
background: #4a4a4a;
}
.collapsible-header .arrow {
transition: transform 0.2s;
}
.collapsible-header.active .arrow {
transform: rotate(90deg);
}
.collapsible-content {
display: none;
padding: 15px;
background: #2d2d2d;
border-radius: 0 0 4px 4px;
}
.collapsible-content.active {
display: block;
}
/* Route-Map Builder Styles */
.route-map-statement {
background: #1e1e1e;
padding: 15px;
margin-bottom: 15px;
border-radius: 6px;
border-left: 4px solid #4fc3f7;
}
.route-map-statement-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #3e3e42;
}
.route-map-statement-header h5 {
color: #4fc3f7;
margin: 0;
}
.match-set-section {
margin-bottom: 15px;
}
.match-set-section h6 {
color: #81c784;
font-size: 12px;
margin-bottom: 10px;
text-transform: uppercase;
}
.prefix-list-entry,
.as-path-entry {
background: #2d2d2d;
padding: 10px;
margin-bottom: 8px;
border-radius: 4px;
display: grid;
grid-template-columns: 80px 100px 1fr 80px 80px 40px;
gap: 10px;
align-items: center;
}
.prefix-list-entry input,
.prefix-list-entry select,
.as-path-entry input,
.as-path-entry select {
padding: 6px;
font-size: 12px;
}
.entry-actions {
display: flex;
gap: 5px;
justify-content: center;
}
.entry-actions button {
background: #e57373;
border: none;
padding: 4px 8px;
border-radius: 3px;
cursor: pointer;
color: #000;
font-size: 11px;
font-weight: bold;
}
.info-box, .peer-info-box {
background: #1e3a5f;
padding: 15px;
border-radius: 4px;
margin-bottom: 15px;
border-left: 4px solid #4fc3f7;
}
.peer-info-box h4 {
color: #4fc3f7;
margin-bottom: 10px;
font-size: 14px;
}
.peer-info-row {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.peer-info-row:last-child {
border-bottom: none;
}
.peer-info-label {
color: #81c784;
font-weight: bold;
font-size: 12px;
}
.peer-info-value {
color: #e0e0e0;
font-size: 12px;
font-family: 'Courier New', monospace;
}
.community-badge {
display: inline-block;
background: #9c27b0;
color: #fff;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
margin-right: 4px;
}
.attribute-tag {
display: inline-block;
background: #555;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
margin-right: 4px;
}
.attribute-tag.changed {
background: #ff9800;
color: #000;
}
.status-badge {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
}
.status-badge.established {
background: #81c784;
color: #000;
}
.status-badge.configured {
background: #ff9800;
color: #000;
}
.status-badge.filtered {
background: #e57373;
color: #fff;
}
#notification {
position: fixed;
top: 80px;
right: 20px;
background: #4fc3f7;
color: #000;
padding: 15px 20px;
border-radius: 6px;
font-weight: bold;
z-index: 2000;
display: none;
box-shadow: 0 4px 6px rgba(0,0,0,0.3);
max-width: 400px;
}
#notification.show {
display: block;
animation: slideIn 0.3s ease-out;
}
#notification.error {
background: #e57373;
color: #fff;
}
#notification.success {
background: #81c784;
color: #000;
}
@keyframes slideIn {
from {
transform: translateX(400px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.summary-section {
margin-bottom: 20px;
}
.summary-section h4 {
color: #81c784;
margin-bottom: 10px;
font-size: 14px;
}
.summary-item {
background: #2d2d2d;
padding: 8px;
margin-bottom: 5px;
border-radius: 4px;
font-size: 13px;
}
.edge-legend {
background: #2d2d2d;
padding: 15px;
border-radius: 4px;
margin-top: 15px;
}
.edge-legend h5 {
color: #81c784;
margin-bottom: 10px;
font-size: 12px;
}
.legend-item {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
font-size: 11px;
}
.legend-line {
width: 40px;
height: 3px;
border-radius: 2px;
}
.legend-line.established {
background: #81c784;
}
.legend-line.configured {
background: #ff9800;
}
.legend-line.ibgp {
background: #4fc3f7;
border: 2px dashed #4fc3f7;
height: 1px;
}
.legend-line.ebgp {
background: #81c784;
}
.legend-line.best-path {
background: #66bb6a;
height: 5px;
}
.legend-line.backup-path {
background: #ffca28;
height: 3px;
}
.legend-line.filtered-path {
background: #ef5350;
height: 2px;
border: 1px dotted #ef5350;
}
.legend-line.has-localas {
background: #ba68c8;
border: 2px dotted #ba68c8;
height: 2px;
}
.empty-state {
text-align: center;
padding: 30px;
color: #9e9e9e;
font-style: italic;
}
/* Phase 3.5: Validation Panel */
.validation-panel {
margin-top: 15px;
background: #2d2d2d;
border-radius: 4px;
padding: 10px;
max-height: 200px;
overflow-y: auto;
}
.validation-panel h4 {
color: #ffca28;
font-size: 12px;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 5px;
}
.warning-item {
background: #3e2723;
border-left: 3px solid #ff9800;
padding: 8px;
margin-bottom: 6px;
border-radius: 3px;
font-size: 11px;
}
.warning-item.error {
background: #4a1a1a;
border-left-color: #ef5350;
}
.warning-item.success {
background: #1b3a1b;
border-left-color: #66bb6a;
}
.warning-item .warning-title {
font-weight: bold;
color: #ff9800;
margin-bottom: 3px;
}
.warning-item.error .warning-title {
color: #ef5350;
}
.warning-item.success .warning-title {
color: #66bb6a;
}
.warning-item .warning-fix {
color: #81c784;
cursor: pointer;
text-decoration: underline;
margin-top: 3px;
display: inline-block;
}
.warning-item .warning-fix:hover {
color: #a5d6a7;
}
.validate-btn {
margin-top: 10px;
}
.template-card:hover {
border-color: #4fc3f7;
background: #3a3a3a;
transform: scale(1.02);
box-shadow: 0 4px 8px rgba(79, 195, 247, 0.3);
}
/* Beginner/Advanced Mode */
.advanced-only {
display: block;
}
body.beginner-mode .advanced-only {
display: none !important;
}
/* Decision Process Viewer */
.decision-step {
background: #2d2d2d;
padding: 12px;
margin-bottom: 8px;
border-radius: 4px;
border-left: 4px solid #555;
}
.decision-step.passed {
border-left-color: #81c784;
}
.decision-step.failed {
border-left-color: #9e9e9e;
}
.decision-step.winner {
border-left-color: #4fc3f7;
background: #1a3a4a;
}
.decision-step-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
}
.decision-step-title {
font-weight: bold;
font-size: 12px;
}
.decision-step.passed .decision-step-title {
color: #81c784;
}
.decision-step.failed .decision-step-title {
color: #9e9e9e;
}
.decision-step.winner .decision-step-title {
color: #4fc3f7;
}
.decision-step-result {
font-size: 11px;
color: #e0e0e0;
}
.decision-comparison {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 10px;
align-items: center;
margin-top: 8px;
font-size: 11px;
}
.decision-route {
padding: 6px 10px;
background: #1a1a1a;
border-radius: 4px;
font-family: 'Courier New', monospace;
}
.decision-operator {
color: #ffca28;
font-weight: bold;
}
/* Bulk Selection Highlight */
.cy-edge.bulk-selected {
line-color: #ffca28 !important;
target-arrow-color: #ffca28 !important;
width: 5 !important;
}
/* Help Tooltips */
.help-icon {
display: inline-block;
width: 16px;
height: 16px;
background: #4fc3f7;
color: #000;
border-radius: 50%;
text-align: center;
line-height: 16px;
font-size: 12px;
font-weight: bold;
cursor: help;
margin-left: 5px;
position: relative;
}
.help-icon:hover::after {
content: attr(data-tooltip);
position: absolute;
left: 25px;
top: -5px;
background: #1a1a1a;
color: #e0e0e0;
padding: 10px;
border-radius: 4px;
border: 1px solid #4fc3f7;
width: 300px;
font-size: 11px;
font-weight: normal;
line-height: 1.4;
z-index: 1000;
white-space: normal;
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
}
.help-icon:hover::before {
content: '';
position: absolute;
left: 20px;
top: 3px;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-right: 5px solid #4fc3f7;
z-index: 1001;
}
Phương thức menu chính sách
Phương thức danh sách tiền tố
Phương thức danh sách đường dẫn AS
Phương thức danh sách cộng đồng
Phương thức bản đồ lộ trình
Phương thức nút
Phương thức cạnh nâng cao với danh sách thả xuống Bản đồ lộ trình
Phương thức thư viện mẫu
Phương thức xem quy trình quyết định BGP
💡 Bắt đầu nhanh:
• Kéo bộ định tuyến/nhà cung cấp dịch vụ vào canvas
• Nhấp vào "🔗 Tạo ngang hàng" rồi nhấp vào hai nút
• Nhấp vào "📋 Đối tượng chính sách ➕" để tạo danh sách tiền tố & bản đồ lộ trình
• Nhấp đúp vào ngang hàng để áp dụng bản đồ lộ trình
• Bấm vào "XXX️ Chạy mô phỏng" để xem kết quả
• Kéo bộ định tuyến/nhà cung cấp dịch vụ vào canvas
• Nhấp vào "🔗 Tạo ngang hàng" rồi nhấp vào hai nút
• Nhấp vào "📋 Đối tượng chính sách ➕" để tạo danh sách tiền tố & bản đồ lộ trình
• Nhấp đúp vào ngang hàng để áp dụng bản đồ lộ trình
• Bấm vào "XXX️ Chạy mô phỏng" để xem kết quả
Không có bộ định tuyến nào được chọn