Text Generation
PEFT
Safetensors
GGUF
English
lora
cisco
networking
security
wazuh
incident-response
network-automation
restconf
ospf
bgp
conversational
Instructions to use JoeiBanana/ai-network-llms with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use JoeiBanana/ai-network-llms with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use JoeiBanana/ai-network-llms with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf JoeiBanana/ai-network-llms:Q4_K_M # Run inference directly in the terminal: llama cli -hf JoeiBanana/ai-network-llms:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf JoeiBanana/ai-network-llms:Q4_K_M # Run inference directly in the terminal: llama cli -hf JoeiBanana/ai-network-llms:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf JoeiBanana/ai-network-llms:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf JoeiBanana/ai-network-llms:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf JoeiBanana/ai-network-llms:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf JoeiBanana/ai-network-llms:Q4_K_M
Use Docker
docker model run hf.co/JoeiBanana/ai-network-llms:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use JoeiBanana/ai-network-llms with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "JoeiBanana/ai-network-llms" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "JoeiBanana/ai-network-llms", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/JoeiBanana/ai-network-llms:Q4_K_M
- Ollama
How to use JoeiBanana/ai-network-llms with Ollama:
ollama run hf.co/JoeiBanana/ai-network-llms:Q4_K_M
- Unsloth Desktop
- Pi
How to use JoeiBanana/ai-network-llms with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf JoeiBanana/ai-network-llms:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "JoeiBanana/ai-network-llms:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use JoeiBanana/ai-network-llms with Docker Model Runner:
docker model run hf.co/JoeiBanana/ai-network-llms:Q4_K_M
- Lemonade
How to use JoeiBanana/ai-network-llms with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull JoeiBanana/ai-network-llms:Q4_K_M
Run and chat with the model
lemonade run user.ai-network-llms-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use JoeiBanana/ai-network-llms with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf JoeiBanana/ai-network-llms:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default JoeiBanana/ai-network-llms:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use JoeiBanana/ai-network-llms with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf JoeiBanana/ai-network-llms:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "JoeiBanana/ai-network-llms:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Upload batch 1/8
Browse files- .gitattributes +5 -32
- .gitignore +45 -0
- backend/app/api/incident.py +0 -0
- backend/app/core/config.py +30 -0
- backend/app/llm/translator_llm.py +55 -0
- backend/app/main.py +0 -0
- backend/app/net/restconf_client.py +55 -0
- backend/app/pipeline/incident_router.py +178 -0
- backend/app/pipeline/pipeline.py +54 -0
- cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_interface_gi0_1.txt +12 -0
- cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_ip_bgp_neighbors_192.0.2.2.txt +9 -0
- cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_ip_bgp_summary.txt +8 -0
- cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_logging_include_bgp.txt +6 -0
- cases/bgp1_test_incidents/incident1_session_flap/EDGE-R1/show_ip_bgp_neighbors.txt +4 -0
- cases/bgp1_test_incidents/incident1_session_flap/EDGE-R1/show_ip_bgp_summary.txt +2 -0
- cases/bgp1_test_incidents/incident1_session_flap/EDGE-RTR1/show_ip_bgp_neighbors_203.0.113.1.txt +5 -0
- cases/bgp1_test_incidents/incident1_session_flap/EDGE-RTR1/show_ip_bgp_summary.txt +5 -0
- cases/bgp1_test_incidents/incident1_session_flap/incident_info.json +3 -0
- cases/bgp1_test_incidents/incident1_session_flap/wazuh_alert.json +8 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/BRANCH-RTR1/show_ip_bgp_neighbors_198.51.100.1.txt +3 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/BRANCH-RTR1/show_ip_bgp_summary.txt +3 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_interface_gi0_2.txt +7 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_ip_bgp_neighbors_198.51.100.2.txt +7 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_ip_bgp_summary.txt +3 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_logging_include_bgp.txt +4 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/incident_info.json +3 -0
- cases/bgp1_test_incidents/incident2_hold_timer_expiration/wazuh_alert.json +8 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/CORE-R1/show_ip_bgp_neighbors_192.0.2.2.txt +3 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/CORE-R1/show_ip_bgp_summary.txt +3 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/EDGE-RTR1/show_ip_bgp_neighbors_203.0.113.1.txt +6 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/EDGE-RTR1/show_ip_bgp_summary.txt +3 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/EDGE-RTR1/show_logging_include_bgp.txt +3 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/incident_info.json +3 -0
- cases/bgp1_test_incidents/incident3_neighborship_reset/wazuh_alert.json +8 -0
- cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/CORE-R1/show_ip_bgp_neighbors_192.0.2.2.txt +10 -0
- cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/CORE-R1/show_ip_bgp_summary.txt +8 -0
- cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/CORE-R1/show_logging_include_bgp.txt +3 -0
- cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/EDGE-RTR1/show_ip_bgp_summary.txt +3 -0
- cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/incident_info.json +3 -0
- cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/wazuh_alert.json +8 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/BRANCH-RTR1/show_run_bgp_snippet.txt +4 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_ip_bgp_community_no_export.txt +3 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_ip_bgp_neighbors_198.51.100.2.txt +10 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_ip_bgp_summary.txt +4 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_logging_include_bgp.txt +3 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/incident_info.json +3 -0
- cases/bgp2_test_incidents/incident2_route_leak_suspected/wazuh_alert.json +8 -0
- cases/bgp2_test_incidents/incident3_path_selection_incorrect/CORE-R1/show_ip_bgp_203.0.113.0_24.txt +14 -0
- cases/bgp2_test_incidents/incident3_path_selection_incorrect/CORE-R1/show_ip_bgp_bestpath.txt +4 -0
- cases/bgp2_test_incidents/incident3_path_selection_incorrect/CORE-R1/show_ip_bgp_neighbors_192.0.2.2_policy.txt +4 -0
.gitattributes
CHANGED
|
@@ -1,35 +1,8 @@
|
|
| 1 |
-
*.
|
| 2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.
|
| 25 |
-
*.
|
| 26 |
-
|
| 27 |
-
*.
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 2 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 4 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.gguf filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ggml filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.gitignore
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Runtime outputs
|
| 2 |
+
show_outputs/
|
| 3 |
+
show_outputs*.zip
|
| 4 |
+
pipeline_stage1.jsonl
|
| 5 |
+
pipeline_fix_output.jsonl
|
| 6 |
+
pipeline_results.jsonl
|
| 7 |
+
results.jsonl
|
| 8 |
+
results_raw.jsonl
|
| 9 |
+
results_raw1.jsonl
|
| 10 |
+
selector_output.jsonl
|
| 11 |
+
selector_output1.jsonl
|
| 12 |
+
s_alerts.jsonl
|
| 13 |
+
alerts_transformed.jsonl
|
| 14 |
+
filtered.json
|
| 15 |
+
filtered_enriched.jsonl
|
| 16 |
+
show_commands.jsonl
|
| 17 |
+
test_llmt_output.jsonl
|
| 18 |
+
cisco_input.jsonl
|
| 19 |
+
cisco_input1.jsonl
|
| 20 |
+
cisco_output.jsonl
|
| 21 |
+
|
| 22 |
+
# Logs
|
| 23 |
+
*.log
|
| 24 |
+
logs.txt
|
| 25 |
+
alerts.txt
|
| 26 |
+
|
| 27 |
+
# Python
|
| 28 |
+
__pycache__/
|
| 29 |
+
*.py[cod]
|
| 30 |
+
*.egg-info/
|
| 31 |
+
.venv/
|
| 32 |
+
venv/
|
| 33 |
+
env/
|
| 34 |
+
|
| 35 |
+
# LoRA checkpoints (keep only final adapter_model.safetensors)
|
| 36 |
+
**/checkpoint-*/
|
| 37 |
+
|
| 38 |
+
# Scratch / test files
|
| 39 |
+
aftertest*.py
|
| 40 |
+
analyze_logs.py
|
| 41 |
+
count_tokens.py
|
| 42 |
+
tesp_ospf4.py
|
| 43 |
+
|
| 44 |
+
# Large temp files
|
| 45 |
+
*.tmp
|
backend/app/api/incident.py
ADDED
|
File without changes
|
backend/app/core/config.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
BASE_DIR = Path(__file__).resolve().parents[3]
|
| 5 |
+
MODELS_DIR = BASE_DIR / "models"
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class ModelRegistry:
|
| 9 |
+
def __init__(self, registry_path: Path):
|
| 10 |
+
if not registry_path.exists():
|
| 11 |
+
raise FileNotFoundError(f"Registry not found: {registry_path}")
|
| 12 |
+
|
| 13 |
+
with open(registry_path, "r", encoding="utf-8") as f:
|
| 14 |
+
self.registry = json.load(f)
|
| 15 |
+
|
| 16 |
+
self.base_model_path = Path(self.registry["base_model_path"])
|
| 17 |
+
self.adapters = self.registry["adapters"]
|
| 18 |
+
|
| 19 |
+
def get_base_model(self) -> Path:
|
| 20 |
+
return self.base_model_path
|
| 21 |
+
|
| 22 |
+
def get_adapter(self, name: str) -> Path:
|
| 23 |
+
if name not in self.adapters:
|
| 24 |
+
raise KeyError(f"Adapter '{name}' not found in registry")
|
| 25 |
+
return Path(self.adapters[name])
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
REGISTRY = ModelRegistry(
|
| 29 |
+
registry_path=MODELS_DIR / "registry.json"
|
| 30 |
+
)
|
backend/app/llm/translator_llm.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 2 |
+
from peft import PeftModel
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
from app.core.config import REGISTRY
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class TranslatorLLM:
|
| 9 |
+
def __init__(self):
|
| 10 |
+
base_path = REGISTRY.get_base_model()
|
| 11 |
+
adapter_path = REGISTRY.get_adapter("llm_t")
|
| 12 |
+
|
| 13 |
+
self.tokenizer = AutoTokenizer.from_pretrained(base_path)
|
| 14 |
+
base_model = AutoModelForCausalLM.from_pretrained(
|
| 15 |
+
base_path,
|
| 16 |
+
torch_dtype=torch.float16,
|
| 17 |
+
device_map="auto"
|
| 18 |
+
)
|
| 19 |
+
self.model = PeftModel.from_pretrained(base_model, adapter_path)
|
| 20 |
+
|
| 21 |
+
def translate(self, cli_commands: list[str], mode: str) -> list[dict]:
|
| 22 |
+
"""
|
| 23 |
+
mode = 'show' -> RESTCONF GET
|
| 24 |
+
mode = 'fix' -> RESTCONF PATCH/POST
|
| 25 |
+
"""
|
| 26 |
+
prompt = self._build_prompt(cli_commands, mode)
|
| 27 |
+
|
| 28 |
+
inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
|
| 29 |
+
outputs = self.model.generate(
|
| 30 |
+
**inputs,
|
| 31 |
+
max_new_tokens=512,
|
| 32 |
+
do_sample=False
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 36 |
+
return self._parse_restconf(text)
|
| 37 |
+
|
| 38 |
+
def _build_prompt(self, cli_commands: list[str], mode: str) -> str:
|
| 39 |
+
header = (
|
| 40 |
+
"Convert the following Cisco CLI commands into RESTCONF API calls.\n"
|
| 41 |
+
f"Mode: {mode.upper()}\n"
|
| 42 |
+
"Return ONLY valid JSON.\n\n"
|
| 43 |
+
)
|
| 44 |
+
body = "\n".join(cli_commands)
|
| 45 |
+
return header + body
|
| 46 |
+
|
| 47 |
+
def _parse_restconf(self, output: str) -> list[dict]:
|
| 48 |
+
"""
|
| 49 |
+
Očakáva JSON array RESTCONF callov.
|
| 50 |
+
"""
|
| 51 |
+
import json
|
| 52 |
+
try:
|
| 53 |
+
return json.loads(output)
|
| 54 |
+
except Exception:
|
| 55 |
+
raise ValueError(f"Invalid RESTCONF output:\n{output}")
|
backend/app/main.py
ADDED
|
File without changes
|
backend/app/net/restconf_client.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 2 |
+
from peft import PeftModel
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
from app.core.config import REGISTRY
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class TranslatorLLM:
|
| 9 |
+
def __init__(self):
|
| 10 |
+
base_path = REGISTRY.get_base_model()
|
| 11 |
+
adapter_path = REGISTRY.get_adapter("llm_t")
|
| 12 |
+
|
| 13 |
+
self.tokenizer = AutoTokenizer.from_pretrained(base_path)
|
| 14 |
+
base_model = AutoModelForCausalLM.from_pretrained(
|
| 15 |
+
base_path,
|
| 16 |
+
torch_dtype=torch.float16,
|
| 17 |
+
device_map="auto"
|
| 18 |
+
)
|
| 19 |
+
self.model = PeftModel.from_pretrained(base_model, adapter_path)
|
| 20 |
+
|
| 21 |
+
def translate(self, cli_commands: list[str], mode: str) -> list[dict]:
|
| 22 |
+
"""
|
| 23 |
+
mode = 'show' -> RESTCONF GET
|
| 24 |
+
mode = 'fix' -> RESTCONF PATCH/POST
|
| 25 |
+
"""
|
| 26 |
+
prompt = self._build_prompt(cli_commands, mode)
|
| 27 |
+
|
| 28 |
+
inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
|
| 29 |
+
outputs = self.model.generate(
|
| 30 |
+
**inputs,
|
| 31 |
+
max_new_tokens=512,
|
| 32 |
+
do_sample=False
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 36 |
+
return self._parse_restconf(text)
|
| 37 |
+
|
| 38 |
+
def _build_prompt(self, cli_commands: list[str], mode: str) -> str:
|
| 39 |
+
header = (
|
| 40 |
+
"Convert the following Cisco CLI commands into RESTCONF API calls.\n"
|
| 41 |
+
f"Mode: {mode.upper()}\n"
|
| 42 |
+
"Return ONLY valid JSON.\n\n"
|
| 43 |
+
)
|
| 44 |
+
body = "\n".join(cli_commands)
|
| 45 |
+
return header + body
|
| 46 |
+
|
| 47 |
+
def _parse_restconf(self, output: str) -> list[dict]:
|
| 48 |
+
"""
|
| 49 |
+
Očakáva JSON array RESTCONF callov.
|
| 50 |
+
"""
|
| 51 |
+
import json
|
| 52 |
+
try:
|
| 53 |
+
return json.loads(output)
|
| 54 |
+
except Exception:
|
| 55 |
+
raise ValueError(f"Invalid RESTCONF output:\n{output}")
|
backend/app/pipeline/incident_router.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
from dataclasses import dataclass
|
| 3 |
+
from typing import Dict, Any, Optional
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
@dataclass(frozen=True)
|
| 7 |
+
class RouteDecision:
|
| 8 |
+
"""
|
| 9 |
+
Výsledok rozhodnutia: ktorý incident model použiť.
|
| 10 |
+
adapter_key musí existovať v registry.json (REGISTRY.get_adapter(adapter_key))
|
| 11 |
+
"""
|
| 12 |
+
adapter_key: str
|
| 13 |
+
domain: str
|
| 14 |
+
reason: str
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class IncidentRouter:
|
| 18 |
+
"""
|
| 19 |
+
Deterministický router pre výber incident LLM.
|
| 20 |
+
|
| 21 |
+
Vstupy:
|
| 22 |
+
- wazuh_alert: dict (z LLM1 / priamo z Wazuh)
|
| 23 |
+
- evidence_text: Optional[str] (normalizované outputs zo show/RESTCONF)
|
| 24 |
+
|
| 25 |
+
Výstup:
|
| 26 |
+
- RouteDecision(adapter_key=..., domain=..., reason=...)
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
# --- Regex pomocníky ---
|
| 30 |
+
_re_ospf = re.compile(r"\bospf\b|neighbor|adjacency|lsa|lsdb|exstart|exchange", re.IGNORECASE)
|
| 31 |
+
_re_bgp = re.compile(r"\bbgp\b|neighbor|hold|keepalive|prefix|route leak|afi|safi|rib|next-hop", re.IGNORECASE)
|
| 32 |
+
_re_switch = re.compile(r"\bstp\b|spanning-tree|vlan|trunk|native vlan|mac flapp|err-disable|storm", re.IGNORECASE)
|
| 33 |
+
_re_sec = re.compile(r"\bacl\b|access-list|nat\b|spoof|ssh brute|failed login|snmp", re.IGNORECASE)
|
| 34 |
+
_re_service = re.compile(r"\bdns\b|nxdomain|ntp\b|unsync|clock is unsynchronized|arp spoof", re.IGNORECASE)
|
| 35 |
+
|
| 36 |
+
# OSPF sub-incident patterns
|
| 37 |
+
_re_ospf_exstart = re.compile(r"exstart|exchange|mtu mismatch|database exchange", re.IGNORECASE)
|
| 38 |
+
_re_ospf_auth = re.compile(r"auth|authentication|md5|key mismatch", re.IGNORECASE)
|
| 39 |
+
_re_ospf_timers = re.compile(r"hello|dead|timer mismatch", re.IGNORECASE)
|
| 40 |
+
_re_ospf_lsa = re.compile(r"lsa flood|lsdb inconsisten|too many lsa|throttle", re.IGNORECASE)
|
| 41 |
+
|
| 42 |
+
# BGP sub-incident patterns
|
| 43 |
+
_re_bgp_session = re.compile(r"session flap|hold timer|reset|cease|neighbor down|not established", re.IGNORECASE)
|
| 44 |
+
_re_bgp_policy = re.compile(r"prefix limit|route leak|path selection|weight|local-pref", re.IGNORECASE)
|
| 45 |
+
_re_bgp_rib = re.compile(r"missing routes|not in rib|next-hop self|afi|safi|address-family", re.IGNORECASE)
|
| 46 |
+
|
| 47 |
+
# SWITCH sub-incident patterns
|
| 48 |
+
_re_sw_l2 = re.compile(r"mac flapp|stp topology change|err-disable", re.IGNORECASE)
|
| 49 |
+
_re_sw_trunk = re.compile(r"vlan mismatch|trunk negotiation|native vlan mismatch", re.IGNORECASE)
|
| 50 |
+
_re_sw_misc = re.compile(r"lldp|cdp|storm control|broadcast storm", re.IGNORECASE)
|
| 51 |
+
|
| 52 |
+
# SECURITY sub-incident patterns
|
| 53 |
+
_re_sec_acl = re.compile(r"acl blocking|acl misconfig|excessive deny|access-list", re.IGNORECASE)
|
| 54 |
+
_re_sec_fw_nat_spoof = re.compile(r"connection exhaust|nat translation|spoofing suspected|uRPF|ip verify source", re.IGNORECASE)
|
| 55 |
+
_re_sec_bruteforce = re.compile(r"ssh brute|failed login|snmp brute", re.IGNORECASE)
|
| 56 |
+
|
| 57 |
+
# SERVICE sub-incident patterns
|
| 58 |
+
_re_svc_dhcp = re.compile(r"dhcp conflict|dhcp starvation|pool utilization|discover rate|ip conflict", re.IGNORECASE)
|
| 59 |
+
_re_svc_dns_ntp_arp = re.compile(r"dns|nxdomain|ntp|unsync|arp spoof", re.IGNORECASE)
|
| 60 |
+
|
| 61 |
+
def decide(self, wazuh_alert: Dict[str, Any], evidence_text: Optional[str] = None) -> RouteDecision:
|
| 62 |
+
text = self._join_text(wazuh_alert, evidence_text)
|
| 63 |
+
|
| 64 |
+
# 1) Hrubá doména
|
| 65 |
+
domain = self._detect_domain(text)
|
| 66 |
+
|
| 67 |
+
# 2) Sub-router podľa domény
|
| 68 |
+
if domain == "ospf":
|
| 69 |
+
return self._route_ospf(text)
|
| 70 |
+
if domain == "bgp":
|
| 71 |
+
return self._route_bgp(text)
|
| 72 |
+
if domain == "switch":
|
| 73 |
+
return self._route_switch(text)
|
| 74 |
+
if domain == "security":
|
| 75 |
+
return self._route_security(text)
|
| 76 |
+
if domain == "service":
|
| 77 |
+
return self._route_service(text)
|
| 78 |
+
|
| 79 |
+
# fallback: bezpečný default (nič nemení) – môžeš premapovať na "manual_review"
|
| 80 |
+
return RouteDecision(
|
| 81 |
+
adapter_key="incident_manual_review",
|
| 82 |
+
domain="unknown",
|
| 83 |
+
reason="No reliable domain match; route to manual review."
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
# --------------------------
|
| 87 |
+
# Domain detection
|
| 88 |
+
# --------------------------
|
| 89 |
+
def _detect_domain(self, text: str) -> str:
|
| 90 |
+
# poradie je zámerné – aby sa napr. "arp spoofing" neprilepilo k switch
|
| 91 |
+
if self._re_ospf.search(text):
|
| 92 |
+
return "ospf"
|
| 93 |
+
if self._re_bgp.search(text):
|
| 94 |
+
return "bgp"
|
| 95 |
+
if self._re_sec.search(text):
|
| 96 |
+
return "security"
|
| 97 |
+
if self._re_service.search(text):
|
| 98 |
+
return "service"
|
| 99 |
+
if self._re_switch.search(text):
|
| 100 |
+
return "switch"
|
| 101 |
+
return "unknown"
|
| 102 |
+
|
| 103 |
+
# --------------------------
|
| 104 |
+
# OSPF routing
|
| 105 |
+
# --------------------------
|
| 106 |
+
def _route_ospf(self, text: str) -> RouteDecision:
|
| 107 |
+
if self._re_ospf_exstart.search(text):
|
| 108 |
+
return RouteDecision("incident_ospf2", "ospf", "Matched EXSTART/EXCHANGE/MTU patterns.")
|
| 109 |
+
if self._re_ospf_auth.search(text) or self._re_ospf_timers.search(text):
|
| 110 |
+
return RouteDecision("incident_ospf3", "ospf", "Matched auth/timers/network-type mismatch patterns.")
|
| 111 |
+
if self._re_ospf_lsa.search(text):
|
| 112 |
+
return RouteDecision("incident_ospf4", "ospf", "Matched LSA/LSDB/redistribution patterns.")
|
| 113 |
+
# default OSPF adjacency loss/basic
|
| 114 |
+
return RouteDecision("incident_ospf1", "ospf", "Default OSPF adjacency/basic incident.")
|
| 115 |
+
|
| 116 |
+
# --------------------------
|
| 117 |
+
# BGP routing
|
| 118 |
+
# --------------------------
|
| 119 |
+
def _route_bgp(self, text: str) -> RouteDecision:
|
| 120 |
+
if self._re_bgp_session.search(text):
|
| 121 |
+
return RouteDecision("incident_bgp1", "bgp", "Matched session flap/hold timer/reset patterns.")
|
| 122 |
+
if self._re_bgp_policy.search(text):
|
| 123 |
+
return RouteDecision("incident_bgp2", "bgp", "Matched prefix-limit/route-leak/path selection patterns.")
|
| 124 |
+
if self._re_bgp_rib.search(text):
|
| 125 |
+
return RouteDecision("incident_bgp3", "bgp", "Matched RIB/next-hop/AFI-SAFI patterns.")
|
| 126 |
+
# fallback
|
| 127 |
+
return RouteDecision("incident_bgp1", "bgp", "Default BGP incident (session-level fallback).")
|
| 128 |
+
|
| 129 |
+
# --------------------------
|
| 130 |
+
# Switch routing
|
| 131 |
+
# --------------------------
|
| 132 |
+
def _route_switch(self, text: str) -> RouteDecision:
|
| 133 |
+
if self._re_sw_l2.search(text):
|
| 134 |
+
return RouteDecision("incident_switch1", "switch", "Matched MAC flap/STP change/err-disable patterns.")
|
| 135 |
+
if self._re_sw_trunk.search(text):
|
| 136 |
+
return RouteDecision("incident_switch2", "switch", "Matched VLAN/trunk/native VLAN mismatch patterns.")
|
| 137 |
+
if self._re_sw_misc.search(text):
|
| 138 |
+
return RouteDecision("incident_switch3", "switch", "Matched LLDP/CDP/storm-control patterns.")
|
| 139 |
+
return RouteDecision("incident_switch1", "switch", "Default switch incident (L2 fallback).")
|
| 140 |
+
|
| 141 |
+
# --------------------------
|
| 142 |
+
# Security routing
|
| 143 |
+
# --------------------------
|
| 144 |
+
def _route_security(self, text: str) -> RouteDecision:
|
| 145 |
+
if self._re_sec_acl.search(text):
|
| 146 |
+
return RouteDecision("incident_sec1", "security", "Matched ACL-related patterns.")
|
| 147 |
+
if self._re_sec_fw_nat_spoof.search(text):
|
| 148 |
+
return RouteDecision("incident_sec2", "security", "Matched FW/NAT/spoofing patterns.")
|
| 149 |
+
if self._re_sec_bruteforce.search(text):
|
| 150 |
+
return RouteDecision("incident_sec3", "security", "Matched SSH/SNMP brute force patterns.")
|
| 151 |
+
return RouteDecision("incident_sec1", "security", "Default security incident (ACL fallback).")
|
| 152 |
+
|
| 153 |
+
# --------------------------
|
| 154 |
+
# Service routing
|
| 155 |
+
# --------------------------
|
| 156 |
+
def _route_service(self, text: str) -> RouteDecision:
|
| 157 |
+
if self._re_svc_dhcp.search(text):
|
| 158 |
+
return RouteDecision("incident_service1", "service", "Matched DHCP/IP conflict/starvation patterns.")
|
| 159 |
+
if self._re_svc_dns_ntp_arp.search(text):
|
| 160 |
+
return RouteDecision("incident_service2", "service", "Matched DNS/NTP/ARP spoofing patterns.")
|
| 161 |
+
return RouteDecision("incident_service2", "service", "Default service incident fallback.")
|
| 162 |
+
|
| 163 |
+
# --------------------------
|
| 164 |
+
# Helpers
|
| 165 |
+
# --------------------------
|
| 166 |
+
@staticmethod
|
| 167 |
+
def _join_text(wazuh_alert: Dict[str, Any], evidence_text: Optional[str]) -> str:
|
| 168 |
+
parts = []
|
| 169 |
+
# vyber najdôležitejšie polia – robustné aj pri rozdielnych schemách
|
| 170 |
+
for k in ("rule", "event", "description", "severity", "device", "src_ip", "agent_name"):
|
| 171 |
+
v = wazuh_alert.get(k)
|
| 172 |
+
if v is not None:
|
| 173 |
+
parts.append(f"{k}: {v}")
|
| 174 |
+
# ak je alert celý už normalizovaný, prilep aj jeho raw json
|
| 175 |
+
parts.append(str(wazuh_alert))
|
| 176 |
+
if evidence_text:
|
| 177 |
+
parts.append(evidence_text)
|
| 178 |
+
return "\n".join(parts)
|
backend/app/pipeline/pipeline.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from app.llm.translator_llm import TranslatorLLM
|
| 2 |
+
from app.net.restconf_client import RestconfClient
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class IncidentPipeline:
|
| 6 |
+
def __init__(self, inventory: dict):
|
| 7 |
+
"""
|
| 8 |
+
inventory = {
|
| 9 |
+
"CORE-R1": {
|
| 10 |
+
"restconf_url": "...",
|
| 11 |
+
"username": "...",
|
| 12 |
+
"password": "..."
|
| 13 |
+
}
|
| 14 |
+
}
|
| 15 |
+
"""
|
| 16 |
+
self.inventory = inventory
|
| 17 |
+
self.translator = TranslatorLLM()
|
| 18 |
+
|
| 19 |
+
def run(
|
| 20 |
+
self,
|
| 21 |
+
device: str,
|
| 22 |
+
show_cli: list[str],
|
| 23 |
+
fix_cli: list[str] | None = None
|
| 24 |
+
) -> dict:
|
| 25 |
+
# ---- SHOW PHASE ----
|
| 26 |
+
show_rest = self.translator.translate(show_cli, mode="show")
|
| 27 |
+
|
| 28 |
+
client = self._get_client(device)
|
| 29 |
+
show_results = client.execute(show_rest)
|
| 30 |
+
|
| 31 |
+
# ---- INCIDENT LLM by tu reálne bežala ----
|
| 32 |
+
# fix_cli = incident_llm(wazuh_alert, show_results)
|
| 33 |
+
|
| 34 |
+
fix_results = None
|
| 35 |
+
if fix_cli:
|
| 36 |
+
fix_rest = self.translator.translate(fix_cli, mode="fix")
|
| 37 |
+
fix_results = client.execute(fix_rest)
|
| 38 |
+
|
| 39 |
+
return {
|
| 40 |
+
"device": device,
|
| 41 |
+
"show": show_results,
|
| 42 |
+
"fix": fix_results
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
def _get_client(self, device: str) -> RestconfClient:
|
| 46 |
+
if device not in self.inventory:
|
| 47 |
+
raise KeyError(f"Device '{device}' not found in inventory")
|
| 48 |
+
|
| 49 |
+
d = self.inventory[device]
|
| 50 |
+
return RestconfClient(
|
| 51 |
+
base_url=d["restconf_url"],
|
| 52 |
+
username=d["username"],
|
| 53 |
+
password=d["password"]
|
| 54 |
+
)
|
cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_interface_gi0_1.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
GigabitEthernet0/1 is up, line protocol is up
|
| 2 |
+
Hardware is iGbE, address is 0c01.1111.0001 (bia 0c01.1111.0001)
|
| 3 |
+
Internet address is 203.0.113.1/30
|
| 4 |
+
MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
|
| 5 |
+
reliability 255/255, txload 1/255, rxload 1/255
|
| 6 |
+
Encapsulation ARPA, loopback not set
|
| 7 |
+
Keepalive set (10 sec)
|
| 8 |
+
Full Duplex, 1000Mbps, media type is RJ45
|
| 9 |
+
5 minute input rate 12000 bits/sec, 15 packets/sec
|
| 10 |
+
5 minute output rate 11000 bits/sec, 14 packets/sec
|
| 11 |
+
5 minute input errors 0, CRC 0, frame 0, overrun 0, ignored 0
|
| 12 |
+
5 minute output errors 0, collisions 0, interface resets 6
|
cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_ip_bgp_neighbors_192.0.2.2.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 192.0.2.2, remote AS 65002, external link
|
| 2 |
+
BGP version 4, remote router ID 2.2.2.2
|
| 3 |
+
BGP state = Established, up for 00:02:14
|
| 4 |
+
Last reset 00:00:31, due to Peer reset
|
| 5 |
+
External BGP neighbor may be up to 1 hops away.
|
| 6 |
+
Connection state is ESTAB, I/O status: 1, unread input bytes: 0
|
| 7 |
+
Keepalive interval is 10 seconds, hold time is 30 seconds
|
| 8 |
+
Received 1250 messages, 0 notifications, 0 in queue
|
| 9 |
+
Sent 1310 messages, 1 notifications, 0 in queue
|
cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 1.1.1.1, local AS number 65001
|
| 2 |
+
BGP table version is 112, main routing table version 112
|
| 3 |
+
2 network entries using 288 bytes of memory
|
| 4 |
+
2 path entries using 160 bytes of memory
|
| 5 |
+
|
| 6 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 7 |
+
192.0.2.2 4 65002 1250 1310 112 0 0 00:02:14 15
|
| 8 |
+
198.51.100.2 4 65100 980 965 112 0 0 03:12:40 20
|
cases/bgp1_test_incidents/incident1_session_flap/CORE-R1/show_logging_include_bgp.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Nov 21 12:07:11.123: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Down Peer reset
|
| 2 |
+
Nov 21 12:07:18.447: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Up
|
| 3 |
+
Nov 21 12:08:02.002: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Down Peer reset
|
| 4 |
+
Nov 21 12:08:10.887: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Up
|
| 5 |
+
Nov 21 12:09:44.551: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Down Peer reset
|
| 6 |
+
Nov 21 12:09:52.331: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Up
|
cases/bgp1_test_incidents/incident1_session_flap/EDGE-R1/show_ip_bgp_neighbors.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 192.0.2.2, remote AS 65002
|
| 2 |
+
BGP state = Idle
|
| 3 |
+
Last reset due to Hold Timer Expired
|
| 4 |
+
Connections dropped 17 times
|
cases/bgp1_test_incidents/incident1_session_flap/EDGE-R1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 2 |
+
192.0.2.2 4 65002 1023 998 0 0 0 00:01:12 Idle
|
cases/bgp1_test_incidents/incident1_session_flap/EDGE-RTR1/show_ip_bgp_neighbors_203.0.113.1.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 203.0.113.1, remote AS 65001, external link
|
| 2 |
+
BGP version 4, remote router ID 1.1.1.1
|
| 3 |
+
BGP state = Established, up for 00:02:13
|
| 4 |
+
Last reset 00:00:39, due to Peer reset
|
| 5 |
+
Keepalive interval is 10 seconds, hold time is 30 seconds
|
cases/bgp1_test_incidents/incident1_session_flap/EDGE-RTR1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 2.2.2.2, local AS number 65002
|
| 2 |
+
BGP table version is 98, main routing table version 98
|
| 3 |
+
|
| 4 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 5 |
+
203.0.113.1 4 65001 1309 1249 98 0 0 00:02:13 15
|
cases/bgp1_test_incidents/incident1_session_flap/incident_info.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"description": "BGP session flap between CORE-R1 (AS65001) and EDGE-RTR1 (AS65002) over Gi0/1"
|
| 3 |
+
}
|
cases/bgp1_test_incidents/incident1_session_flap/wazuh_alert.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rule": "BGP session flap detected",
|
| 3 |
+
"device": "CORE-R1",
|
| 4 |
+
"severity": "high",
|
| 5 |
+
"description": "BGP neighbor 192.0.2.2 is flapping frequently (multiple resets in short time).",
|
| 6 |
+
"timestamp": "2025-11-21T12:10:00Z",
|
| 7 |
+
"neighbor": "192.0.2.2"
|
| 8 |
+
}
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/BRANCH-RTR1/show_ip_bgp_neighbors_198.51.100.1.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 198.51.100.1, remote AS 65001, external link
|
| 2 |
+
BGP state = Established, up for 00:01:02
|
| 3 |
+
Keepalive interval is 60 seconds, hold time is 180 seconds
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/BRANCH-RTR1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 3.3.3.3, local AS number 65010
|
| 2 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 3 |
+
198.51.100.1 4 65001 610 522 55 0 0 00:01:02 12
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_interface_gi0_2.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
GigabitEthernet0/2 is up, line protocol is up
|
| 2 |
+
Internet address is 198.51.100.1/30
|
| 3 |
+
MTU 1500 bytes
|
| 4 |
+
5 minute input rate 2000 bits/sec, 3 packets/sec
|
| 5 |
+
5 minute output rate 1800 bits/sec, 2 packets/sec
|
| 6 |
+
input errors 0, CRC 0, frame 0, overrun 0, ignored 0
|
| 7 |
+
output errors 0, collisions 0, interface resets 0
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_ip_bgp_neighbors_198.51.100.2.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 198.51.100.2, remote AS 65010, external link
|
| 2 |
+
BGP version 4, remote router ID 3.3.3.3
|
| 3 |
+
BGP state = Active
|
| 4 |
+
Last reset 00:00:12, due to Hold timer expired
|
| 5 |
+
Keepalive interval is 10 seconds, hold time is 30 seconds
|
| 6 |
+
Last read 00:00:31, Last write 00:00:08
|
| 7 |
+
Connections established 14; dropped 14
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 1.1.1.1, local AS number 65001
|
| 2 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 3 |
+
198.51.100.2 4 65010 522 610 112 0 0 00:00:12 Active
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/CORE-R1/show_logging_include_bgp.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Nov 21 12:19:40.900: %BGP-3-NOTIFICATION: sent to neighbor 198.51.100.2 4/0 (hold time expired) 0 bytes
|
| 2 |
+
Nov 21 12:19:40.901: %BGP-5-ADJCHANGE: neighbor 198.51.100.2 Down Hold Timer Expired
|
| 3 |
+
Nov 21 12:19:53.114: %BGP-5-ADJCHANGE: neighbor 198.51.100.2 Up
|
| 4 |
+
Nov 21 12:19:59.227: %BGP-5-ADJCHANGE: neighbor 198.51.100.2 Down Hold Timer Expired
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/incident_info.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"description": "BGP resets due to hold timer expiration between CORE-R1 (AS65001) and BRANCH-RTR1 (AS65010)"
|
| 3 |
+
}
|
cases/bgp1_test_incidents/incident2_hold_timer_expiration/wazuh_alert.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rule": "BGP hold timer expiration",
|
| 3 |
+
"device": "CORE-R1",
|
| 4 |
+
"severity": "critical",
|
| 5 |
+
"description": "BGP neighbor 198.51.100.2 reset due to hold timer expiration.",
|
| 6 |
+
"timestamp": "2025-11-21T12:20:00Z",
|
| 7 |
+
"neighbor": "198.51.100.2"
|
| 8 |
+
}
|
cases/bgp1_test_incidents/incident3_neighborship_reset/CORE-R1/show_ip_bgp_neighbors_192.0.2.2.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 192.0.2.2, remote AS 65002, external link
|
| 2 |
+
BGP state = Established, up for 00:10:24
|
| 3 |
+
Route refresh: advertised and received (old & new)
|
cases/bgp1_test_incidents/incident3_neighborship_reset/CORE-R1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 1.1.1.1, local AS number 65001
|
| 2 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 3 |
+
192.0.2.2 4 65002 2190 2251 112 0 0 00:10:24 15
|
cases/bgp1_test_incidents/incident3_neighborship_reset/EDGE-RTR1/show_ip_bgp_neighbors_203.0.113.1.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 203.0.113.1, remote AS 65001, external link
|
| 2 |
+
BGP version 4, remote router ID 1.1.1.1
|
| 3 |
+
BGP state = Established, up for 00:10:22
|
| 4 |
+
Last reset 00:00:58, due to Cease/other configuration change
|
| 5 |
+
Route refresh: advertised and received (old & new)
|
| 6 |
+
Inbound soft reconfiguration allowed
|
cases/bgp1_test_incidents/incident3_neighborship_reset/EDGE-RTR1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 2.2.2.2, local AS number 65002
|
| 2 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 3 |
+
203.0.113.1 4 65001 2250 2190 98 0 0 00:10:22 15
|
cases/bgp1_test_incidents/incident3_neighborship_reset/EDGE-RTR1/show_logging_include_bgp.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Nov 21 12:28:59.010: %BGP-5-ADJCHANGE: neighbor 203.0.113.1 Down Cease/other configuration change
|
| 2 |
+
Nov 21 12:29:03.552: %BGP-5-ADJCHANGE: neighbor 203.0.113.1 Up
|
| 3 |
+
Nov 21 12:29:05.120: %BGP-5-ROUTECHANGE: neighbor 203.0.113.1 soft reset (inbound)
|
cases/bgp1_test_incidents/incident3_neighborship_reset/incident_info.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"description": "BGP neighborship reset after policy change; prefer soft clear to refresh routes"
|
| 3 |
+
}
|
cases/bgp1_test_incidents/incident3_neighborship_reset/wazuh_alert.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rule": "BGP neighborship reset detected",
|
| 3 |
+
"device": "EDGE-RTR1",
|
| 4 |
+
"severity": "medium",
|
| 5 |
+
"description": "BGP session reset/cleared detected for neighbor 203.0.113.1 (policy change).",
|
| 6 |
+
"timestamp": "2025-11-21T12:30:00Z",
|
| 7 |
+
"neighbor": "203.0.113.1"
|
| 8 |
+
}
|
cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/CORE-R1/show_ip_bgp_neighbors_192.0.2.2.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 192.0.2.2, remote AS 65002, external link
|
| 2 |
+
BGP version 4, remote router ID 2.2.2.2
|
| 3 |
+
BGP state = Idle (Admin), down for 00:00:18
|
| 4 |
+
Last reset 00:00:18, due to Cease/Maximum Number of Prefixes Reached
|
| 5 |
+
Last notification: Cease/Maximum Number of Prefixes Reached
|
| 6 |
+
Graceful Restart is enabled
|
| 7 |
+
Route refresh: advertised and received (new)
|
| 8 |
+
Keepalive interval is 30 seconds, hold time is 180 seconds
|
| 9 |
+
Maximum prefixes allowed 1000 (threshold 80%), warning-only is disabled
|
| 10 |
+
Prefixes received 1254, accepted 1254
|
cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/CORE-R1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 1.1.1.1, local AS number 65001
|
| 2 |
+
BGP table version is 812, main routing table version 812
|
| 3 |
+
2005 network entries using 288720 bytes of memory
|
| 4 |
+
4100 path entries using 328000 bytes of memory
|
| 5 |
+
|
| 6 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 7 |
+
192.0.2.2 4 65002 98231 98190 812 0 0 00:00:18 Idle (Admin)
|
| 8 |
+
198.51.100.2 4 65100 22110 22005 812 0 0 06:22:10 420
|
cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/CORE-R1/show_logging_include_bgp.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Nov 22 09:09:41.120: %BGP-3-NOTIFICATION: sent to neighbor 192.0.2.2 6/1 (Maximum Number of Prefixes Reached) 0 bytes
|
| 2 |
+
Nov 22 09:09:41.121: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Down Cease/Maximum Number of Prefixes Reached
|
| 3 |
+
Nov 22 09:09:42.005: %BGP-5-ADJCHANGE: neighbor 192.0.2.2 Down (Admin)
|
cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/EDGE-RTR1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 2.2.2.2, local AS number 65002
|
| 2 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 3 |
+
203.0.113.1 4 65001 98190 98231 511 0 0 00:00:20 980
|
cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/incident_info.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"description": "Prefix limit exceeded on CORE-R1 from neighbor 192.0.2.2 (transit). Session torn down by max-prefix protection."
|
| 3 |
+
}
|
cases/bgp2_test_incidents/incident1_prefix_limit_exceeded/wazuh_alert.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rule": "BGP maximum-prefix limit exceeded",
|
| 3 |
+
"device": "CORE-R1",
|
| 4 |
+
"severity": "critical",
|
| 5 |
+
"description": "Neighbor 192.0.2.2 exceeded maximum-prefix limit; session reset to protect routing table.",
|
| 6 |
+
"timestamp": "2025-11-22T09:10:00Z",
|
| 7 |
+
"neighbor": "192.0.2.2"
|
| 8 |
+
}
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/BRANCH-RTR1/show_run_bgp_snippet.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
router bgp 65010
|
| 2 |
+
neighbor 198.51.100.1 remote-as 65001
|
| 3 |
+
! WARNING: missing outbound route-map to restrict advertisements
|
| 4 |
+
! no prefix-list / route-map applied
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_ip_bgp_community_no_export.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
CORE-R1#show ip bgp community no-export
|
| 2 |
+
% Network not in table
|
| 3 |
+
% No entries were displayed.
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_ip_bgp_neighbors_198.51.100.2.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 198.51.100.2, remote AS 65010, external link
|
| 2 |
+
BGP version 4, remote router ID 3.3.3.3
|
| 3 |
+
BGP state = Established, up for 01:12:44
|
| 4 |
+
Route refresh: advertised and received (new)
|
| 5 |
+
Keepalive interval is 30 seconds, hold time is 180 seconds
|
| 6 |
+
Inbound prefix policy: NONE
|
| 7 |
+
Outbound prefix policy: NONE
|
| 8 |
+
Community policy: send-community both
|
| 9 |
+
Prefixes received 18420, accepted 18400
|
| 10 |
+
Neighbor capabilities: route-refresh, 4-byte AS
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_ip_bgp_summary.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP router identifier 1.1.1.1, local AS number 65001
|
| 2 |
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
| 3 |
+
198.51.100.2 4 65010 55210 55001 812 0 0 01:12:44 18400
|
| 4 |
+
192.0.2.2 4 65002 98231 98190 812 0 0 06:40:10 980
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/CORE-R1/show_logging_include_bgp.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Nov 22 09:20:05.331: %BGP-5-ADJCHANGE: neighbor 198.51.100.2 Up
|
| 2 |
+
Nov 22 09:22:10.110: %BGP-4-MAXPREFIX: No max-prefix configured for neighbor 198.51.100.2; received-prefixes=18420
|
| 3 |
+
Nov 22 09:22:12.771: %BGP-4-ROUTELEAK: Possible route leak detected from 198.51.100.2 (prefix-count anomaly)
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/incident_info.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"description": "Route leak suspected: customer BRANCH-RTR1 is advertising full internet table to CORE-R1 (missing no-export / wrong policy)."
|
| 3 |
+
}
|
cases/bgp2_test_incidents/incident2_route_leak_suspected/wazuh_alert.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rule": "BGP route leak suspected",
|
| 3 |
+
"device": "CORE-R1",
|
| 4 |
+
"severity": "high",
|
| 5 |
+
"description": "Unusual spike of prefixes from neighbor 198.51.100.2; possible customer route leak.",
|
| 6 |
+
"timestamp": "2025-11-22T09:25:00Z",
|
| 7 |
+
"neighbor": "198.51.100.2"
|
| 8 |
+
}
|
cases/bgp2_test_incidents/incident3_path_selection_incorrect/CORE-R1/show_ip_bgp_203.0.113.0_24.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP routing table entry for 203.0.113.0/24, version 999
|
| 2 |
+
Paths: (2 available, best #1, table default)
|
| 3 |
+
Advertised to update-groups:
|
| 4 |
+
1
|
| 5 |
+
65100
|
| 6 |
+
198.51.100.2 from 198.51.100.2 (4.4.4.4)
|
| 7 |
+
Origin IGP, metric 0, localpref 200, valid, external, best
|
| 8 |
+
Community: 65100:50
|
| 9 |
+
rx pathid: 0, tx pathid: 0
|
| 10 |
+
65002
|
| 11 |
+
192.0.2.2 from 192.0.2.2 (2.2.2.2)
|
| 12 |
+
Origin IGP, metric 0, localpref 100, valid, external
|
| 13 |
+
Community: 65002:100
|
| 14 |
+
rx pathid: 0, tx pathid: 0
|
cases/bgp2_test_incidents/incident3_path_selection_incorrect/CORE-R1/show_ip_bgp_bestpath.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
CORE-R1#show ip bgp bestpath
|
| 2 |
+
BGP Bestpath Algorithm is enabled
|
| 3 |
+
Paths are selected based on:
|
| 4 |
+
Weight, Local Preference, Locally originated, AS path, Origin, MED, eBGP/iBGP, IGP metric, Router ID
|
cases/bgp2_test_incidents/incident3_path_selection_incorrect/CORE-R1/show_ip_bgp_neighbors_192.0.2.2_policy.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BGP neighbor is 192.0.2.2, remote AS 65002, external link
|
| 2 |
+
Inbound route-map: NONE
|
| 3 |
+
Outbound route-map: NONE
|
| 4 |
+
Route refresh: advertised and received (new)
|