Skip to content
This repository was archived by the owner on Feb 10, 2018. It is now read-only.

Commit 3406130

Browse files
authored
Merge pull request #154 from mirceaulinic/bgp-neighbors-fix
Refactor get_bgp_neighbors_detail
2 parents 55f770d + 1726148 commit 3406130

12 files changed

+900
-361
lines changed

napalm_junos/junos.py

+88-83
Original file line numberDiff line numberDiff line change
@@ -782,11 +782,6 @@ def build_prefix_limit(**args):
782782
def get_bgp_neighbors_detail(self, neighbor_address=''):
783783
"""Detailed view of the BGP neighbors operational data."""
784784
bgp_neighbors = {}
785-
bgp_neighbors_table = junos_views.junos_bgp_neighbors_table(self.device)
786-
bgp_neighbors_table.get(
787-
neighbor_address=neighbor_address
788-
)
789-
bgp_neighbors_items = bgp_neighbors_table.items()
790785
default_neighbor_details = {
791786
'up': False,
792787
'local_as': 0,
@@ -824,7 +819,6 @@ def get_bgp_neighbors_detail(self, neighbor_address=''):
824819
'advertised_prefix_count': -1,
825820
'flap_count': 0
826821
}
827-
828822
OPTION_KEY_MAP = {
829823
'RemovePrivateAS': 'remove_private_as',
830824
'Multipath': 'multipath',
@@ -836,87 +830,98 @@ def get_bgp_neighbors_detail(self, neighbor_address=''):
836830
# Preference, HoldTime, Ttl, LogUpDown, Refresh
837831
}
838832

839-
JUNOS_DEFAULT_VRF_TABLES = (
840-
'inet.0',
841-
'inet6.0',
842-
'inetflow.0'
843-
)
833+
def _bgp_iter_core(neighbor_data, instance=None):
834+
'''
835+
Iterate over a list of neighbors.
836+
For older junos, the routing instance is not specified inside the
837+
BGP neighbors XML, therefore we need to use a super sub-optimal structure
838+
as in get_bgp_neighbors: iterate through the list of network instances
839+
then execute one request for each and every routing instance.
840+
For newer junos, this is not necessary as the routing instance is available
841+
and we can get everything solve in a single request.
842+
'''
843+
for bgp_neighbor in neighbor_data:
844+
remote_as = int(bgp_neighbor[0])
845+
neighbor_details = deepcopy(default_neighbor_details)
846+
neighbor_details.update(
847+
{elem[0]: elem[1] for elem in bgp_neighbor[1] if elem[1] is not None}
848+
)
849+
if not instance:
850+
peer_fwd_rti = neighbor_details.pop('peer_fwd_rti')
851+
instance = peer_fwd_rti
852+
else:
853+
peer_fwd_rti = neighbor_details.pop('peer_fwd_rti', '')
854+
instance_name = 'global' if instance == 'master' else instance
855+
options = neighbor_details.pop('options', '')
856+
if isinstance(options, str):
857+
options_list = options.split()
858+
for option in options_list:
859+
key = OPTION_KEY_MAP.get(option)
860+
if key is not None:
861+
neighbor_details[key] = True
862+
four_byte_as = neighbor_details.pop('4byte_as', 0)
863+
local_address = neighbor_details.pop('local_address', '')
864+
local_details = local_address.split('+')
865+
neighbor_details['local_address'] = napalm_base.helpers.convert(
866+
napalm_base.helpers.ip, local_details[0], local_details[0])
867+
if len(local_details) == 2:
868+
neighbor_details['local_port'] = int(local_details[1])
869+
else:
870+
neighbor_details['local_port'] = 179
871+
neighbor_details['suppress_4byte_as'] = (remote_as != four_byte_as)
872+
peer_address = neighbor_details.pop('peer_address', '')
873+
remote_details = peer_address.split('+')
874+
neighbor_details['remote_address'] = napalm_base.helpers.convert(
875+
napalm_base.helpers.ip, remote_details[0], remote_details[0])
876+
if len(remote_details) == 2:
877+
neighbor_details['remote_port'] = int(remote_details[1])
878+
else:
879+
neighbor_details['remote_port'] = 179
880+
neighbor_details['routing_table'] = instance_name
881+
neighbors_rib = neighbor_details.pop('rib')
882+
neighbors_queue = neighbor_details.pop('queue')
883+
messages_queued_out = 0
884+
for queue_entry in neighbors_queue.items():
885+
messages_queued_out += queue_entry[1][0][1]
886+
neighbor_details['messages_queued_out'] = messages_queued_out
887+
if instance_name not in bgp_neighbors.keys():
888+
bgp_neighbors[instance_name] = {}
889+
if remote_as not in bgp_neighbors[instance_name].keys():
890+
bgp_neighbors[instance_name][remote_as] = []
891+
neighbor_rib_stats = neighbors_rib.items()
892+
if not neighbor_rib_stats:
893+
bgp_neighbors[instance_name][remote_as].append(neighbor_details)
894+
continue # no RIBs available, pass default details
895+
neighbor_rib_details = {
896+
'active_prefix_count': 0,
897+
'received_prefix_count': 0,
898+
'accepted_prefix_count': 0,
899+
'suppressed_prefix_count': 0,
900+
'advertised_prefix_count': 0
901+
}
902+
for rib_entry in neighbor_rib_stats:
903+
for elem in rib_entry[1]:
904+
neighbor_rib_details[elem[0]] += elem[1]
905+
neighbor_details.update(neighbor_rib_details)
906+
bgp_neighbors[instance_name][remote_as].append(neighbor_details)
844907

845908
old_junos = napalm_base.helpers.convert(
846909
int, self.device.facts.get('version', '0.0').split('.')[0], '0') < 13
910+
bgp_neighbors_table = junos_views.junos_bgp_neighbors_table(self.device)
847911

848-
for bgp_neighbor in bgp_neighbors_items:
849-
remote_as = int(bgp_neighbor[0])
850-
neighbor_details = deepcopy(default_neighbor_details)
851-
neighbor_details.update(
852-
{elem[0]: elem[1] for elem in bgp_neighbor[1] if elem[1] is not None}
853-
)
854-
options = neighbor_details.pop('options', '')
855-
if isinstance(options, str):
856-
options_list = options.split()
857-
for option in options_list:
858-
key = OPTION_KEY_MAP.get(option)
859-
if key is not None:
860-
neighbor_details[key] = True
861-
four_byte_as = neighbor_details.pop('4byte_as', 0)
862-
local_address = neighbor_details.pop('local_address', '')
863-
local_details = local_address.split('+')
864-
neighbor_details['local_address'] = napalm_base.helpers.convert(
865-
napalm_base.helpers.ip, local_details[0], local_details[0])
866-
if len(local_details) == 2:
867-
neighbor_details['local_port'] = int(local_details[1])
868-
else:
869-
neighbor_details['local_port'] = 179
870-
neighbor_details['suppress_4byte_as'] = (remote_as != four_byte_as)
871-
peer_address = neighbor_details.pop('peer_address', '')
872-
remote_details = peer_address.split('+')
873-
neighbor_details['remote_address'] = napalm_base.helpers.convert(
874-
napalm_base.helpers.ip, remote_details[0], remote_details[0])
875-
if len(remote_details) == 2:
876-
neighbor_details['remote_port'] = int(remote_details[1])
877-
else:
878-
neighbor_details['remote_port'] = 179
879-
neighbors_rib = neighbor_details.pop('rib')
880-
neighbors_queue = neighbor_details.pop('queue')
881-
if old_junos:
882-
# anyway need to pop both
883-
# for Junos < 13, under the bgp-output-queue hierarchy
884-
# the table-name does not exist, hence we cannot match
885-
# but each table has an index that we can use later
886-
# the structure under old_queue is similar to queue,
887-
# but the key is the integer representing the table ID
888-
neighbors_queue = neighbor_details.pop('old_queue')
889-
else:
890-
neighbor_details.pop('old_queue')
891-
neighbor_queue_rib = {}
892-
for queue_entry in neighbors_queue.items():
893-
neighbor_queue_rib[queue_entry[0]] = queue_entry[1][0][1]
894-
rib_id = 0
895-
if not old_junos:
896-
# for Junos >= 13, the table index starts from 1,
897-
# while older versions have 0 as the first table
898-
rib_id += 1
899-
for rib_entry in neighbors_rib.items():
900-
_table = py23_compat.text_type(rib_entry[0])
901-
if _table in JUNOS_DEFAULT_VRF_TABLES:
902-
_table = 'global'
903-
if _table not in bgp_neighbors.keys():
904-
bgp_neighbors[_table] = {}
905-
if remote_as not in bgp_neighbors[_table].keys():
906-
bgp_neighbors[_table][remote_as] = []
907-
neighbor_rib_details = deepcopy(neighbor_details)
908-
neighbor_rib_details.update({
909-
elem[0]: elem[1] for elem in rib_entry[1]
910-
})
911-
if old_junos:
912-
# in some cases this information might not exist at all...
913-
neighbor_rib_details['messages_queued_out'] = \
914-
neighbor_queue_rib.get(str(rib_id), -1)
915-
else:
916-
neighbor_rib_details['messages_queued_out'] = neighbor_queue_rib[rib_entry[0]]
917-
neighbor_rib_details['routing_table'] = py23_compat.text_type(rib_entry[0])
918-
bgp_neighbors[_table][remote_as].append(neighbor_rib_details)
919-
rib_id += 1
912+
if old_junos:
913+
instances = junos_views.junos_route_instance_table(self.device)
914+
for instance, instance_data in instances.get().items():
915+
if instance.startswith('__'):
916+
# junos internal instances
917+
continue
918+
neighbor_data = bgp_neighbors_table.get(instance=instance,
919+
neighbor_address=neighbor_address).items()
920+
_bgp_iter_core(neighbor_data, instance=instance)
921+
else:
922+
bgp_neighbors_table = junos_views.junos_bgp_neighbors_table(self.device)
923+
neighbor_data = bgp_neighbors_table.get(neighbor_address=neighbor_address).items()
924+
_bgp_iter_core(neighbor_data)
920925
return bgp_neighbors
921926

922927
def get_arp_table(self):

napalm_junos/utils/junos_views.yml

+3-10
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ junos_bgp_tables_summary_view:
330330

331331
junos_bgp_neighbors_table:
332332
rpc: get-bgp-neighbor-information
333+
args:
334+
instance: ''
333335
args_key: neighbor_address
334336
item: bgp-peer
335337
key: peer-as
@@ -341,6 +343,7 @@ junos_bgp_neighbors_view:
341343
local_as: {local-as: int}
342344
remote_as: {peer-as: int}
343345
router_id: {peer-id: unicode}
346+
peer_fwd_rti: peer-fwd-rti
344347
local_address: local-address
345348
peer_address: peer-address
346349
options: bgp-option-information/bgp-options
@@ -361,7 +364,6 @@ junos_bgp_neighbors_view:
361364
configured_keepalive: {keepalive-interval: int}
362365
rib: junos_bgp_rib_table
363366
queue: junos_bgp_queue_table
364-
old_queue: junos_bgp_old_queue_table
365367
flap_count: {flap-count: int}
366368

367369
junos_bgp_queue_table:
@@ -373,15 +375,6 @@ junos_bgp_queue_view:
373375
fields:
374376
messages_queued_out: {count: int}
375377

376-
junos_bgp_old_queue_table:
377-
item: bgp-output-queue
378-
key: number
379-
view: junos_bgp_old_queue_view
380-
381-
junos_bgp_old_queue_view:
382-
fields:
383-
messages_queued_out: {count: int}
384-
385378
junos_bgp_rib_table:
386379
item: bgp-rib
387380
key: name

0 commit comments

Comments
 (0)