Update modules/visual_route.py

This commit is contained in:
Blackwhitebear8 2025-07-06 17:32:17 +02:00
parent 9a0553fd5d
commit 402edf0784

View file

@ -67,10 +67,11 @@ def _parse_bgp_paths_to_graph(bgp_data: str) -> dict:
for line in lines[paths_header_index + 1:]: for line in lines[paths_header_index + 1:]:
stripped_line = line.strip() stripped_line = line.strip()
if not stripped_line: continue if not stripped_line: continue
is_new_path_line = False is_new_path_line = False
if line.startswith(' ') and not line.startswith(' '): if line.startswith(' ') and not line.startswith(' '):
first_word = stripped_line.split(' ')[0] first_word = stripped_line.split(' ')[0].replace(',', '')
if first_word.isdigit() or stripped_line == "Local": if first_word.isdigit():
is_new_path_line = True is_new_path_line = True
if is_new_path_line: if is_new_path_line:
@ -83,32 +84,30 @@ def _parse_bgp_paths_to_graph(bgp_data: str) -> dict:
except StopIteration: except StopIteration:
return {"nodes": [], "edges": []} return {"nodes": [], "edges": []}
all_paths_info, best_path_info = [], None all_paths_info = []
best_path_info = None
for block in path_blocks: for block in path_blocks:
block_text = "\n".join(block)
clean_lines = [line for line in block if not line.strip().startswith("AddPath ID:")] clean_lines = [line for line in block if not line.strip().startswith("AddPath ID:")]
block_text_for_check = "\n".join(clean_lines) block_text_for_check = "\n".join(clean_lines)
is_best = bool(re.search(r'\bbest\b', block_text_for_check, re.IGNORECASE)) is_best = bool(re.search(r'\bbest\b', block_text_for_check, re.IGNORECASE))
is_multipath = 'multipath' in block_text_for_check.lower() is_multipath = 'multipath' in block_text_for_check.lower()
block_text_full = "\n".join(block)
path_line = block[0].strip() path_line = block[0].strip()
path_asns_raw = [] path_asns_raw = []
if path_line != "Local": for part in path_line.split(' '):
for part in path_line.split(' '): clean_part = part.replace(',', '').strip()
clean_part = part.replace(',', '').strip() if clean_part.isdigit():
if clean_part.isdigit(): path_asns_raw.append(clean_part)
path_asns_raw.append(clean_part) else:
else: break
break
path_asns = list(dict.fromkeys(path_asns_raw)) path_asns = list(dict.fromkeys(path_asns_raw))
local_pref_match = re.search(r'localpref (\d+)', block_text_full) local_pref_match = re.search(r'localpref (\d+)', block_text)
local_pref = int(local_pref_match.group(1)) if local_pref_match else None local_pref = int(local_pref_match.group(1)) if local_pref_match else None
next_hop_match = re.search(r'^\s*([\da-fA-F:.]+)\s+from', block_text_full, re.MULTILINE) next_hop_match = re.search(r'^\s*([\da-fA-F:.]+)\s+from', block_text, re.MULTILINE)
next_hop = next_hop_match.group(1) if next_hop_match else None next_hop = next_hop_match.group(1) if next_hop_match else None
community_match = re.search(r'Large Community: ([\d:]+)', block_text_full) community_match = re.search(r'Large Community: ([\d:]+)', block_text)
community = community_match.group(1) if community_match else None community = community_match.group(1) if community_match else None
category = 'other' category = 'other'
if community: if community:
@ -135,37 +134,27 @@ def _parse_bgp_paths_to_graph(bgp_data: str) -> dict:
y_pos_counter_up, y_pos_counter_down = 1, 1 y_pos_counter_up, y_pos_counter_down = 1, 1
for i, path_info in enumerate(ordered_paths): for i, path_info in enumerate(ordered_paths):
lane_y = 0 lane_y = 0
if not path_info['is_best']: if i > 0:
if y_pos_counter_up <= y_pos_counter_down: if y_pos_counter_up <= y_pos_counter_down: lane_y = y_pos_counter_up * Y_SEPARATION; y_pos_counter_up += 1
lane_y = y_pos_counter_up * Y_SEPARATION else: lane_y = -y_pos_counter_down * Y_SEPARATION; y_pos_counter_down += 1
y_pos_counter_up += 1
else:
lane_y = -y_pos_counter_down * Y_SEPARATION
y_pos_counter_down += 1
style, is_active_path = {}, False style, is_active_path = {}, False
if path_info['is_best']: if path_info['is_best']:
style = {"node_color": '#FADBD8', "edge_color": '#C0392B', "width": 3, "dashes": False, "path_type": " (best)"} style = {"node_color": '#FADBD8', "edge_color": '#C0392B', "width": 3, "dashes": False, "path_type": " (best)"}; is_active_path = True
is_active_path = True
elif path_info['is_multipath']: elif path_info['is_multipath']:
style = {"node_color": '#FDEBD0', "edge_color": '#F39C12', "width": 2, "dashes": False, "path_type": " (multipath)"} style = {"node_color": '#FDEBD0', "edge_color": '#F39C12', "width": 2, "dashes": False, "path_type": " (multipath)"}; is_active_path = True
is_active_path = True
else: else:
style = {"node_color": '#D6DBDF', "edge_color": '#2C3E50', "width": 1, "dashes": True, "path_type": ""} style = {"node_color": '#D6DBDF', "edge_color": '#2C3E50', "width": 1, "dashes": True, "path_type": ""}; is_active_path = False
is_active_path = False
path_node_ids = [] path_node_ids = []
for j, asn in enumerate(path_info['asns']): for j, asn in enumerate(path_info['asns']):
unique_node_id = f"AS{asn}-{i}" unique_node_id = f"AS{asn}-{i}"
path_node_ids.append(unique_node_id) path_node_ids.append(unique_node_id)
as_name = AS_NAME_CACHE.get(asn, "") as_name = AS_NAME_CACHE.get(asn, ""); wrapped_name = '\n'.join(textwrap.wrap(as_name, width=AS_NAME_WRAP_WIDTH)) if as_name else ""
wrapped_name = '\n'.join(textwrap.wrap(as_name, width=AS_NAME_WRAP_WIDTH)) if as_name else ""
base_label = f"<b>AS{asn}</b>" base_label = f"<b>AS{asn}</b>"
if j == 0 and path_info['local_pref'] is not None: if j == 0 and path_info['local_pref'] is not None: base_label += f" (LP: {path_info['local_pref']})"
base_label += f" (LP: {path_info['local_pref']})"
label = f"{base_label}\n{wrapped_name}" label = f"{base_label}\n{wrapped_name}"
if j == 0 and path_info['next_hop']: if j == 0 and path_info['next_hop']: label += f"\n<i>Next Hop: {path_info['next_hop']}{style['path_type']}</i>"
label += f"\n<i>Next Hop: {path_info['next_hop']}{style['path_type']}</i>"
nodes.append({"id": unique_node_id, "label": label, "color": style['node_color'], "x": (j + 1) * X_SEPARATION, "y": lane_y, "fixed": True, "path_category": path_info['category'], "is_active": is_active_path}) nodes.append({"id": unique_node_id, "label": label, "color": style['node_color'], "x": (j + 1) * X_SEPARATION, "y": lane_y, "fixed": True, "path_category": path_info['category'], "is_active": is_active_path})
full_chain = [ROUTER_NAME] + path_node_ids + [prefix] full_chain = [ROUTER_NAME] + path_node_ids + [prefix]