@@ -232,92 +232,126 @@ def get_interfaces_counters(self):
232232
233233 return interface_counters
234234
235+ @staticmethod
236+ def _parse_neigbor_info (line ):
237+ m = re .match ('BGP neighbor is (?P<neighbor>.*?), remote AS (?P<as>.*?), .*' , line )
238+ return m .group ('neighbor' ), m .group ('as' )
239+
240+ @staticmethod
241+ def _parse_rid_info (line ):
242+ m = re .match ('.*BGP version 4, remote router ID (?P<rid>.*?), VRF (?P<vrf>.*?)$' , line )
243+ return m .group ('rid' ), m .group ('vrf' )
244+
245+ @staticmethod
246+ def _parse_desc (line ):
247+ m = re .match ('\s+Description: (?P<description>.*?)' , line )
248+ if m :
249+ return m .group ('description' )
250+ else :
251+ return None
252+
253+ @staticmethod
254+ def _parse_local_info (line ):
255+ m = re .match ('Local AS is (?P<as>.*?),.*' , line )
256+ return m .group ('as' )
257+
258+ @staticmethod
259+ def _parse_prefix_info (line ):
260+ m = re .match ('(\s*?)(?P<af>IPv[46]) Unicast:\s*(?P<sent>\d+)\s*(?P<received>\d+)' , line )
261+ return m .group ('sent' ), m .group ('received' )
262+
235263 def get_bgp_neighbors (self ):
264+ NEIGHBOR_FILTER = 'bgp neighbors vrf all | include remote AS | remote router ID |^\s*IPv[46] Unicast:.*[0-9]+|^Local AS|Desc'
265+ output_summary_cmds = self .device .run_commands (
266+ ['show ipv6 bgp summary vrf all' , 'show ip bgp summary vrf all' ],
267+ encoding = 'json' )
268+ output_neighbor_cmds = self .device .run_commands (
269+ ['show ip ' + NEIGHBOR_FILTER , 'show ipv6 ' + NEIGHBOR_FILTER ],
270+ encoding = 'text' )
271+
272+ bgp_counters = defaultdict (lambda : dict (peers = dict ()))
273+ for summary in output_summary_cmds :
274+ """
275+ Json output looks as follows
276+ "vrfs": {
277+ "default": {
278+ "routerId": 1,
279+ "asn": 1,
280+ "peers": {
281+ "1.1.1.1": {
282+ "msgSent": 1,
283+ "inMsgQueue": 0,
284+ "prefixReceived": 3926,
285+ "upDownTime": 1449501378.418644,
286+ "version": 4,
287+ "msgReceived": 59616,
288+ "prefixAccepted": 3926,
289+ "peerState": "Established",
290+ "outMsgQueue": 0,
291+ "underMaintenance": false,
292+ "asn": 1
293+ }
294+ }
295+ }
296+ }
297+ """
298+ for vrf , vrf_data in summary ['vrfs' ].iteritems ():
299+ bgp_counters [vrf ]['router_id' ] = vrf_data ['routerId' ]
300+ for peer , peer_data in vrf_data ['peers' ].iteritems ():
301+ peer_info = {
302+ 'is_up' : peer_data ['peerState' ] == 'Established' ,
303+ 'is_enabled' : peer_data ['peerState' ] == 'Established' or peer_data ['peerState' ] == 'Active' ,
304+ 'uptime' : int (peer_data ['upDownTime' ])
305+ }
306+ bgp_counters [vrf ]['peers' ][peer ] = peer_info
307+ lines = []
308+ [lines .extend (x ['output' ].splitlines ()) for x in output_neighbor_cmds ]
309+ for line in lines :
310+ """
311+ Raw output from the command looks like the following:
312+
313+ BGP neighbor is 1.1.1.1, remote AS 1, external link
314+ Description: Very info such descriptive
315+ BGP version 4, remote router ID 1.1.1.1, VRF my_vrf
316+ IPv4 Unicast: 683 78
317+ IPv6 Unicast: 0 0
318+ Local AS is 2, local router ID 2.2.2.2
319+ """
320+ if line is '' :
321+ continue
322+ neighbor , r_as = self ._parse_neigbor_info (lines .pop (0 ))
323+ # this line can be either description or rid info
324+ next_line = lines .pop (0 )
325+ desc = self ._parse_desc (next_line )
326+ if desc is None :
327+ rid , vrf = self ._parse_rid_info (next_line )
328+ desc = ''
329+ else :
330+ rid , vrf = self ._parse_rid_info (lines .pop (0 ))
331+
332+ v4_sent , v4_recv = self ._parse_prefix_info (lines .pop (0 ))
333+ v6_sent , v6_recv = self ._parse_prefix_info (lines .pop (0 ))
334+ local_as = self ._parse_local_info (lines .pop (0 ))
335+ data = {
336+ 'remote_as' : int (r_as ),
337+ 'remote_id' : unicode (rid ),
338+ 'local_as' : int (local_as ),
339+ 'description' : unicode (desc ),
340+ 'address_family' : {
341+ 'ipv4' : {
342+ 'sent_prefixes' : int (v4_sent ),
343+ 'received_prefixes' : int (v4_recv ),
344+ 'accepted_prefixes' : - 1
345+ },
346+ 'ipv6' : {
347+ 'sent_prefixes' : int (v6_sent ),
348+ 'received_prefixes' : int (v6_recv ),
349+ 'accepted_prefixes' : - 1
350+ }
351+ }
352+ }
353+ bgp_counters [vrf ]['peers' ][neighbor ].update (data )
236354
237- commands_json = list ()
238- commands_txt = list ()
239- commands_json .append ('show ip bgp summary vrf all' )
240- commands_json .append ('show ipv6 bgp summary vrf all' )
241- commands_txt .append ('show ip bgp neighbors vrf all | include remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:' )
242- commands_txt .append ('show ipv6 bgp neighbors vrf all | include remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:' )
243-
244- output_summary = self .device .run_commands (commands_json , encoding = 'json' )
245- output_neighbors = self .device .run_commands (commands_txt , encoding = 'text' )
246-
247- ##########################################
248- # no JSON available for show ip bgp neigh
249- # Using 'show ipv[4-6] bgp neighbors vrf all | i remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:'
250- # NOTE: if there is no description, EOS does not print the line.
251-
252-
253- # Regex the output from show ip bgp neigh
254- def get_bgp_neighbor (needed_peer , vrf , output_to_parse ):
255- import re
256-
257- bgp_neighbors = dict ()
258- bgp_peer = dict ()
259- neighbor_regexp = re .compile ('BGP neighbor is (.*?),' )
260- description_regexp = re .compile ('Description: (.*?)$' )
261- remote_id_regexp = re .compile ('remote router ID (.*?),' )
262- vrf_regexp = re .compile ('VRF (.*?)$' )
263- IPv4_sent_regexp = re .compile ('IPv4 Unicast: ( *)(\d*) ' )
264- IPv6_sent_regexp = re .compile ('IPv6 Unicast: ( *)(\d*) ' )
265-
266- for line in output_to_parse .splitlines ():
267- if re .search (neighbor_regexp , line ):
268- peer = re .search (neighbor_regexp , line ).group (1 )
269- bgp_neighbors [peer ] = dict ()
270- bgp_neighbors [peer ]['description' ] = ''
271- continue
272- elif re .search (description_regexp , line ):
273- bgp_neighbors [peer ]['description' ] = re .search (description_regexp , line ).group (1 )
274- continue
275- elif re .search (remote_id_regexp , line ):
276- bgp_neighbors [peer ]['remote_id' ] = re .search (remote_id_regexp , line ).group (1 )
277- bgp_neighbors [peer ]['vrf' ] = re .search (vrf_regexp , line ).group (1 )
278- continue
279- elif re .search (IPv4_sent_regexp , line ):
280- bgp_neighbors [peer ]['ipv4' ] = re .search (IPv4_sent_regexp , line ).group (2 )
281- continue
282- elif re .search (IPv6_sent_regexp , line ):
283- bgp_neighbors [peer ]['ipv6' ] = re .search (IPv6_sent_regexp , line ).group (2 )
284- continue
285- try :
286- peer = next (peer for peer in bgp_neighbors if peer == needed_peer )
287- except StopIteration :
288- raise Exception ("Peer %s not found in show bgp neighbors" % needed_peer )
289- if bgp_neighbors [peer ]['vrf' ] == vrf :
290- bgp_peer ['remote_id' ] = bgp_neighbors [peer ]['remote_id' ]
291- bgp_peer ['description' ] = bgp_neighbors [peer ]['description' ]
292- bgp_peer ['ipv4' ] = bgp_neighbors [peer ]['ipv4' ]
293- bgp_peer ['ipv6' ] = bgp_neighbors [peer ]['ipv6' ]
294- return bgp_peer
295-
296- bgp_counters = defaultdict (dict )
297- for output_id in [0 , 1 ]:
298- for vrf in output_summary [output_id ]['vrfs' ]:
299- bgp_counters [vrf ]['router_id' ] = unicode (output_summary [output_id ]['vrfs' ][vrf ]['routerId' ])
300- bgp_counters [vrf ]['peers' ] = dict ()
301- for peer in output_summary [output_id ]['vrfs' ][vrf ]['peers' ]:
302- bgp_counters [vrf ]['peers' ][peer ] = dict ()
303- bgp_counters [vrf ]['peers' ][peer ]['local_as' ] = int (output_summary [output_id ]['vrfs' ][vrf ]['asn' ])
304- bgp_counters [vrf ]['peers' ][peer ]['remote_as' ] = int (output_summary [output_id ]['vrfs' ][vrf ]['peers' ][peer ]['asn' ])
305- peerState = output_summary [output_id ]['vrfs' ][vrf ]['peers' ][peer ]['peerState' ]
306- bgp_counters [vrf ]['peers' ][peer ]['is_up' ] = peerState == 'Established'
307- if 'peerStateIdleReason' in output_summary [output_id ]['vrfs' ][vrf ]['peers' ][peer ]:
308- bgp_counters [vrf ]['peers' ][peer ]['is_enabled' ] = False
309- else :
310- bgp_counters [vrf ]['peers' ][peer ]['is_enabled' ] = peerState == 'Established' or peerState == 'Active'
311- bgp_counters [vrf ]['peers' ][peer ]['uptime' ] = int (output_summary [output_id ]['vrfs' ][vrf ]['peers' ][peer ]['upDownTime' ])
312- bgp_peer = get_bgp_neighbor (peer , vrf , output_neighbors [output_id ]['output' ])
313- bgp_counters [vrf ]['peers' ][peer ]['remote_id' ] = unicode (bgp_peer ['remote_id' ])
314- bgp_counters [vrf ]['peers' ][peer ]['description' ] = unicode (bgp_peer ['description' ])
315- bgp_counters [vrf ]['peers' ][peer ]['address_family' ] = dict ()
316- for family in ['ipv4' , 'ipv6' ]:
317- bgp_counters [vrf ]['peers' ][peer ]['address_family' ][family ] = dict ()
318- bgp_counters [vrf ]['peers' ][peer ]['address_family' ][family ]['received_prefixes' ] = int (output_summary [output_id ]['vrfs' ][vrf ]['peers' ][peer ]['prefixReceived' ])
319- bgp_counters [vrf ]['peers' ][peer ]['address_family' ][family ]['accepted_prefixes' ] = int (output_summary [output_id ]['vrfs' ][vrf ]['peers' ][peer ]['prefixAccepted' ])
320- bgp_counters [vrf ]['peers' ][peer ]['address_family' ][family ]['sent_prefixes' ] = int (bgp_peer [family ])
321355 if 'default' in bgp_counters .keys ():
322356 bgp_counters ['global' ] = bgp_counters .pop ('default' )
323357 return bgp_counters
0 commit comments