Repository: napalm-automation/napalm

Issue:
Implement `get_bgp_neighbors_detail`
For framework consistency, this seems to be one of the most used methods (at least on Junos and XR).


Discussion:
@mirceaulinic I'll take this one, you can assign me. 
Hi @nickethier. I'm sorry I missed your comment, thankfully someone asked about this so I just saw it. Unfortunately, I cannot assign issues but to folks that are part of the napalm-automation organisation. But please feel free to implement it, and submit a PR once you have anything ready. Thanks!

Resolving patch:
diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py
--- a/napalm/ios/ios.py
+++ b/napalm/ios/ios.py
@@ -24,6 +24,7 @@
 import tempfile
 import telnetlib
 import copy
+from collections import defaultdict
 
 from netmiko import FileTransfer, InLineTransfer
 from napalm.base.base import NetworkDriver
@@ -67,6 +68,20 @@
    'show_mac_address': ['show mac-address-table', 'show mac address-table'],
 }
 
+AFI_COMMAND_MAP = {
+    'IPv4 Unicast': 'ipv4 unicast',
+    'IPv6 Unicast': 'ipv6 unicast',
+    'VPNv4 Unicast': 'vpnv4 all',
+    'VPNv6 Unicast': 'vpnv6 unicast all',
+    'IPv4 Multicast': 'ipv4 multicast',
+    'IPv6 Multicast': 'ipv6 multicast',
+    'L2VPN E-VPN': 'l2vpn evpn',
+    'MVPNv4 Unicast': 'ipv4 mvpn all',
+    'MVPNv6 Unicast': 'ipv6 mvpn all',
+    'VPNv4 Flowspec': 'ipv4 flowspec',
+    'VPNv6 Flowspec': 'ipv6 flowspec',
+}
+
 
 class IOSDriver(NetworkDriver):
     """NAPALM Cisco IOS Handler."""
@@ -1478,6 +1493,104 @@ def get_bgp_neighbors(self):
                 }
         return bgp_neighbor_data
 
+    def get_bgp_neighbors_detail(self, neighbor_address=''):
+        bgp_detail = defaultdict(lambda: defaultdict(lambda: []))
+
+        raw_bgp_sum = self._send_command('show ip bgp all sum').strip()
+        bgp_sum = napalm.base.helpers.textfsm_extractor(
+            self, 'ip_bgp_all_sum', raw_bgp_sum)
+        for neigh in bgp_sum:
+            if neighbor_address and neighbor_address != neigh['neighbor']:
+                continue
+            raw_bgp_neigh = self._send_command('show ip bgp {} neigh {}'.format(
+                AFI_COMMAND_MAP[neigh['addr_family']], neigh['neighbor']))
+            bgp_neigh = napalm.base.helpers.textfsm_extractor(
+                self, 'ip_bgp_neigh', raw_bgp_neigh)[0]
+            details = {
+                'up': neigh['up'] != 'never',
+                'local_as': napalm.base.helpers.as_number(neigh['local_as']),
+                'remote_as': napalm.base.helpers.as_number(neigh['remote_as']),
+                'router_id': napalm.base.helpers.ip(
+                    bgp_neigh['router_id']) if bgp_neigh['router_id'] else '',
+                'local_address': napalm.base.helpers.ip(
+                    bgp_neigh['local_address']) if bgp_neigh['local_address'] else '',
+                'local_address_configured': False,
+                'local_port': napalm.base.helpers.as_number(
+                    bgp_neigh['local_port']) if bgp_neigh['local_port'] else 0,
+                'routing_table': bgp_neigh['vrf'] if bgp_neigh['vrf'] else 'global',
+                'remote_address': napalm.base.helpers.ip(bgp_neigh['neighbor']),
+                'remote_port': napalm.base.helpers.as_number(
+                    bgp_neigh['remote_port']) if bgp_neigh['remote_port'] else 0,
+                'multihop': False,
+                'multipath': False,
+                'remove_private_as': False,
+                'import_policy': '',
+                'export_policy': '',
+                'input_messages': napalm.base.helpers.as_number(
+                    bgp_neigh['msg_total_in']) if bgp_neigh['msg_total_in'] else 0,
+                'output_messages': napalm.base.helpers.as_number(
+                    bgp_neigh['msg_total_out']) if bgp_neigh['msg_total_out'] else 0,
+                'input_updates': napalm.base.helpers.as_number(
+                    bgp_neigh['msg_update_in']) if bgp_neigh['msg_update_in'] else 0,
+                'output_updates': napalm.base.helpers.as_number(
+                    bgp_neigh['msg_update_out']) if bgp_neigh['msg_update_out'] else 0,
+                'messages_queued_out': napalm.base.helpers.as_number(neigh['out_q']),
+                'connection_state': bgp_neigh['bgp_state'],
+                'previous_connection_state': '',
+                'last_event': '',
+                'suppress_4byte_as': (
+                    bgp_neigh['four_byte_as'] != 'advertised and received' if
+                    bgp_neigh['four_byte_as'] else False),
+                'local_as_prepend': False,
+                'holdtime': napalm.base.helpers.as_number(
+                    bgp_neigh['holdtime']) if bgp_neigh['holdtime'] else 0,
+                'configured_holdtime': 0,
+                'keepalive': napalm.base.helpers.as_number(
+                    bgp_neigh['keepalive']) if bgp_neigh['keepalive'] else 0,
+                'configured_keepalive': 0,
+                'active_prefix_count': 0,
+                'received_prefix_count': 0,
+                'accepted_prefix_count': 0,
+                'suppressed_prefix_count': 0,
+                'advertised_prefix_count': 0,
+                'flap_count': 0,
+            }
+
+            bgp_neigh_afi = napalm.base.helpers.textfsm_extractor(
+                self, 'ip_bgp_neigh_afi', raw_bgp_neigh)
+            if len(bgp_neigh_afi) > 1:
+                bgp_neigh_afi = bgp_neigh_afi[1]
+                details.update({
+                    'local_address_configured': bgp_neigh_afi['local_addr_conf'] != '',
+                    'multipath': bgp_neigh_afi['multipaths'] != '0',
+                    'import_policy': bgp_neigh_afi['policy_in'],
+                    'export_policy': bgp_neigh_afi['policy_out'],
+                    'last_event': (
+                        bgp_neigh_afi['last_event'] if
+                        bgp_neigh_afi['last_event'] != 'never' else ''),
+                    'active_prefix_count': napalm.base.helpers.as_number(
+                        bgp_neigh_afi['bestpaths']),
+                    'received_prefix_count': napalm.base.helpers.as_number(
+                        bgp_neigh_afi['prefix_curr_in']) + napalm.base.helpers.as_number(
+                            bgp_neigh_afi['rejected_prefix_in']),
+                    'accepted_prefix_count': napalm.base.helpers.as_number(
+                        bgp_neigh_afi['prefix_curr_in']),
+                    'suppressed_prefix_count': napalm.base.helpers.as_number(
+                        bgp_neigh_afi['rejected_prefix_in']),
+                    'advertised_prefix_count': napalm.base.helpers.as_number(
+                        bgp_neigh_afi['prefix_curr_out']),
+                    'flap_count': napalm.base.helpers.as_number(bgp_neigh_afi['flap_count'])
+                })
+            else:
+                bgp_neigh_afi = bgp_neigh_afi[0]
+                details.update({
+                    'import_policy': bgp_neigh_afi['policy_in'],
+                    'export_policy': bgp_neigh_afi['policy_out'],
+                })
+            bgp_detail[details['routing_table']][
+                details['remote_as']].append(details)
+        return bgp_detail
+
     def get_interfaces_counters(self):
         """
         Return interface counters and errors.


Test patch:
diff --git a/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/expected_result.json b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/expected_result.json
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/expected_result.json
@@ -0,0 +1,162 @@
+{
+    "global": {
+        "2": [
+            {
+                "suppress_4byte_as": false,
+                "local_as_prepend": false,
+                "connection_state": "Established",
+                "multihop": false,
+                "input_messages": 25396694,
+                "output_messages": 271231,
+                "previous_connection_state": "",
+                "remove_private_as": false,
+                "multipath": false,
+                "messages_queued_out": 0,
+                "keepalive": 30,
+                "remote_as": 2,
+                "local_port": 26678,
+                "active_prefix_count": 39815,
+                "configured_holdtime": 0,
+                "routing_table": "global",
+                "flap_count": 0,
+                "suppressed_prefix_count": 24,
+                "local_address": "2.2.2.3",
+                "remote_port": 179,
+                "input_updates": 25127420,
+                "configured_keepalive": 0,
+                "router_id": "2.2.2.1",
+                "export_policy": "bgp-out",
+                "local_as": 1,
+                "remote_address": "2.2.2.2",
+                "advertised_prefix_count": 7,
+                "local_address_configured": true,
+                "import_policy": "bgp-in",
+                "last_event": "",
+                "accepted_prefix_count": 679328,
+                "up": true,
+                "output_updates": 25,
+                "received_prefix_count": 679352,
+                "holdtime": 90
+            }
+        ],
+        "3": [
+            {
+                "suppress_4byte_as": false,
+                "local_as_prepend": false,
+                "connection_state": "Idle",
+                "multihop": false,
+                "input_messages": 0,
+                "output_messages": 0,
+                "previous_connection_state": "",
+                "remove_private_as": false,
+                "multipath": false,
+                "messages_queued_out": 0,
+                "keepalive": 0,
+                "remote_as": 3,
+                "local_port": 0,
+                "active_prefix_count": 0,
+                "configured_holdtime": 0,
+                "routing_table": "global",
+                "flap_count": 0,
+                "suppressed_prefix_count": 0,
+                "local_address": "",
+                "remote_port": 0,
+                "input_updates": 0,
+                "configured_keepalive": 0,
+                "router_id": "0.0.0.0",
+                "export_policy": "bgp-out",
+                "local_as": 1,
+                "remote_address": "3.3.3.3",
+                "advertised_prefix_count": 0,
+                "local_address_configured": false,
+                "import_policy": "bgp-in",
+                "last_event": "",
+                "accepted_prefix_count": 0,
+                "up": false,
+                "output_updates": 0,
+                "received_prefix_count": 0,
+                "holdtime": 0
+            }
+        ],
+        "7922": [
+            {
+                "suppress_4byte_as": false,
+                "local_as_prepend": false,
+                "connection_state": "Established",
+                "multihop": false,
+                "input_messages": 6974686,
+                "output_messages": 138790,
+                "previous_connection_state": "",
+                "remove_private_as": false,
+                "multipath": false,
+                "messages_queued_out": 0,
+                "keepalive": 60,
+                "remote_as": 7922,
+                "local_port": 21958,
+                "active_prefix_count": 45715,
+                "configured_holdtime": 0,
+                "routing_table": "global",
+                "flap_count": 0,
+                "suppressed_prefix_count": 0,
+                "local_address": "2001:559::2",
+                "remote_port": 179,
+                "input_updates": 6974616,
+                "configured_keepalive": 0,
+                "router_id": "68.86.1.1",
+                "export_policy": "BGP-TRANSIT-IPv6-OUT",
+                "local_as": 1,
+                "remote_address": "2001:559::1",
+                "advertised_prefix_count": 2,
+                "local_address_configured": true,
+                "import_policy": "BGP-COMCAST-IPv6-IN",
+                "last_event": "",
+                "accepted_prefix_count": 45717,
+                "up": true,
+                "output_updates": 2480,
+                "received_prefix_count": 45717,
+                "holdtime": 180
+            }
+        ]
+    },
+    "internal": {
+        "1": [
+            {
+                "suppress_4byte_as": false,
+                "local_as_prepend": false,
+                "connection_state": "Established",
+                "multihop": false,
+                "input_messages": 102588,
+                "output_messages": 101263,
+                "previous_connection_state": "",
+                "remove_private_as": false,
+                "multipath": false,
+                "messages_queued_out": 0,
+                "keepalive": 60,
+                "remote_as": 1,
+                "local_port": 50308,
+                "active_prefix_count": 880,
+                "configured_holdtime": 0,
+                "routing_table": "internal",
+                "flap_count": 3,
+                "suppressed_prefix_count": 39,
+                "local_address": "169.255.22.2",
+                "remote_port": 179,
+                "input_updates": 1748,
+                "configured_keepalive": 0,
+                "router_id": "10.87.121.3",
+                "export_policy": "announce-to-internal",
+                "local_as": 1,
+                "remote_address": "169.255.22.1",
+                "advertised_prefix_count": 7,
+                "local_address_configured": true,
+                "import_policy": "receive-from-internal",
+                "last_event": "9w0d, due to Active open failed",
+                "accepted_prefix_count": 440,
+                "up": true,
+                "output_updates": 3,
+                "received_prefix_count": 479,
+                "holdtime": 180
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_all_sum.txt b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_all_sum.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_all_sum.txt
@@ -0,0 +1,56 @@
+For address family: IPv4 Unicast
+BGP router identifier 1.1.1.1, local AS number 1
+BGP table version is 64501120, main routing table version 1
+679365 network entries using 168611728 bytes of memory
+679365 path entries using 168611728 bytes of memory
+245318/104673 BGP path/bestpath attribute entries using 66726496 bytes of memory
+209172 BGP AS-PATH entries using 9889312 bytes of memory
+1 BGP ATTR_SET entries using 40 bytes of memory
+631 BGP community entries using 23128 bytes of memory
+4 BGP extended community entries using 96 bytes of memory
+531 BGP route-map cache entries using 33984 bytes of memory
+0 BGP filter-list cache entries using 0 bytes of memory
+BGP using 461950560 total bytes of memory
+110578 received paths for inbound soft reconfiguration
+BGP activity 3436532/2710503 prefixes, 19215241/17575537 paths, scan interval 60 secs
+
+Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
+2.2.2.2         4            2 25389124  271112 64501075    0    0 12w2d      679365
+3.3.3.3         4            3       0       0        1    0    0 never    Idle (Admin)
+
+For address family: IPv6 Unicast
+BGP router identifier 1.1.1.1, local AS number 1
+BGP table version is 1, main routing table version 1
+45646 network entries using 12415712 bytes of memory
+45648 path entries using 6938496 bytes of memory
+37600/18773 BGP path/bestpath attribute entries using 10227200 bytes of memory
+209172 BGP AS-PATH entries using 9889312 bytes of memory
+1 BGP ATTR_SET entries using 40 bytes of memory
+631 BGP community entries using 23128 bytes of memory
+4 BGP extended community entries using 96 bytes of memory
+531 BGP route-map cache entries using 33984 bytes of memory
+0 BGP filter-list cache entries using 0 bytes of memory
+BGP using 39527928 total bytes of memory
+BGP activity 3436532/2710503 prefixes, 19215241/17575537 paths, scan interval 60 secs
+
+Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
+2001:559::1     4         7922 6944479  138054 116434201    0    0 12w2d       45646
+
+For address family: VPNv4 Unicast
+BGP router identifier 1.1.1.1, local AS number 1
+BGP table version is 6668, main routing table version 6668
+440 network entries using 120320 bytes of memory
+926 path entries using 125936 bytes of memory
+49/24 BGP path/bestpath attribute entries using 14112 bytes of memory
+209172 BGP AS-PATH entries using 9889312 bytes of memory
+1 BGP ATTR_SET entries using 40 bytes of memory
+631 BGP community entries using 23128 bytes of memory
+4 BGP extended community entries using 96 bytes of memory
+531 BGP route-map cache entries using 33984 bytes of memory
+0 BGP filter-list cache entries using 0 bytes of memory
+BGP using 10206888 total bytes of memory
+466 received paths for inbound soft reconfiguration
+BGP activity 3436532/2710503 prefixes, 19215241/17575537 paths, scan interval 60 secs
+
+Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
+169.255.22.1    4            1  101841  100528     6668    0    0 9w0d          440
\ No newline at end of file
diff --git a/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv4_unicast_neigh_2_2_2_2.txt b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv4_unicast_neigh_2_2_2_2.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv4_unicast_neigh_2_2_2_2.txt
@@ -0,0 +1,130 @@
+
+BGP neighbor is 2.2.2.2,  remote AS 2, external link
+  BGP version 4, remote router ID 2.2.2.1
+  BGP state = Established, up for 12w2d
+  Last read 00:00:00, last write 00:00:20, hold time is 90, keepalive interval is 30 seconds
+  Neighbor sessions:
+    1 active, is not multisession capable (disabled)
+  Neighbor capabilities:
+    Route refresh: advertised and received(new)
+    Four-octets ASN Capability: advertised and received
+    Address family IPv4 Unicast: advertised and received
+    Graceful Restart Capability: advertised and received
+      Remote Restart timer is 120 seconds
+      Address families advertised by peer:
+        none
+    Enhanced Refresh Capability: advertised
+    Multisession Capability: 
+    Stateful switchover support enabled: NO for session 1
+  Message statistics:
+    InQ depth is 0
+    OutQ depth is 0
+    
+                         Sent       Rcvd
+    Opens:                  1          1
+    Notifications:          0          0
+    Updates:               25   25127420
+    Keepalives:        271205     269273
+    Route Refresh:          0          0
+    Total:             271231   25396694
+  Do log neighbor state changes (via global configuration)
+  Default minimum time between advertisement runs is 30 seconds
+
+ For address family: IPv4 Unicast
+  Session: 2.2.2.2
+  BGP table version 64524347, neighbor version 64524250/64524347
+  Output queue size : 0
+  Index 4, Advertise bit 3
+  4 update-group member
+  Inherits from template ebgp-peer
+  Inbound soft reconfiguration allowed
+  My AS number is allowed for 10 number of times
+  NEXT_HOP is always this router for eBGP paths
+  Community attribute sent to this neighbor
+  Extended-community attribute sent to this neighbor
+  Inbound path policy configured
+  Outbound path policy configured
+  Incoming update prefix filter list is bogons-in
+  Outgoing update prefix filter list is BGP_TO_TRANSIT
+  Route map for incoming advertisements is bgp-in
+  Route map for outgoing advertisements is bgp-out
+  Slow-peer detection is disabled
+  Slow-peer split-update-group dynamic is disabled
+                                 Sent       Rcvd
+  Prefix activity:               ----       ----
+    Prefixes Current:               7     679328 (Consumes 92388608 bytes)
+    Prefixes Total:                68   58397012
+    Implicit Withdraw:             40   49488476
+    Explicit Withdraw:             21    8229208
+    Used as bestpath:             n/a      39815
+    Used as multipath:            n/a          0
+    Used as secondary:            n/a          0
+
+                                   Outbound    Inbound
+  Local Policy Denied Prefixes:    --------    -------
+    AS_PATH too long:                     0         24
+    Other Policies:                29728393        n/a
+    Total:                         29728393         24
+  Number of NLRIs in the update sent: max 6, min 0
+  Last detected as dynamic slow peer: never
+  Dynamic slow peer recovered: never
+  Refresh Epoch: 1
+  Last Sent Refresh Start-of-rib: never
+  Last Sent Refresh End-of-rib: never
+  Last Received Refresh Start-of-rib: never
+  Last Received Refresh End-of-rib: never
+				       Sent	  Rcvd
+	Refresh activity:	       ----	  ----
+	  Refresh Start-of-RIB          0          0
+	  Refresh End-of-RIB            0          0
+
+  Address tracking is enabled, the RIB does have a route to 2.2.2.2
+  Connections established 1; dropped 0
+  Last reset never
+  External BGP neighbor configured for connected checks (single-hop no-disable-connected-check)
+  Interface associated: GigabitEthernet0/0/0 (peering address in same link)
+  Transport(tcp) path-mtu-discovery is enabled
+  Graceful-Restart is enabled, restart-time 120 seconds, stalepath-time 360 seconds
+  SSO is disabled
+Connection state is ESTAB, I/O status: 1, unread input bytes: 0            
+Connection is ECN Disabled, Mininum incoming TTL 0, Outgoing TTL 1
+Local host: 2.2.2.3, Local port: 26678
+Foreign host: 2.2.2.2, Foreign port: 179
+Connection tableid (VRF): 0
+Maximum output segment queue size: 50
+
+Enqueued packets for retransmit: 0, input: 0  mis-ordered: 0 (0 bytes)
+
+Event Timers (current time is 0x1BCABB8E0):
+Timer          Starts    Wakeups            Next
+Retrans        271224          1             0x0
+TimeWait            0          0             0x0
+AckHold      10516474    9279863             0x0
+SendWnd             0          0             0x0
+KeepAlive           0          0             0x0
+GiveUp              0          0             0x0
+PmtuAger      7434532    7434531     0x1BCABB9CD
+DeadWait            0          0             0x0
+Linger              0          0             0x0
+ProcessQ            0          0             0x0
+
+iss: 2752933698  snduna: 2758088150  sndnxt: 2758088150
+irs: 4248710998  rcvnxt: 1912649518
+
+sndwnd:  16384  scale:      0  maxrcvwnd:  16384
+rcvwnd:  15959  scale:      0  delrcvwnd:    425
+
+SRTT: 1000 ms, RTTO: 1003 ms, RTV: 3 ms, KRTT: 0 ms
+minRTT: 0 ms, maxRTT: 1000 ms, ACK hold: 200 ms
+uptime: -1 ms, Sent idletime: 24 ms, Receive idletime: 265 ms 
+Status Flags: active open
+Option Flags: nagle, path mtu capable
+IP Precedence value : 6
+
+Datagrams (max data segment is 1460 bytes):
+Rcvd: 10884457 (out of order: 0), with data: 10651645, total data bytes: 1958905815
+Sent: 10867963 (retransmit: 1, fastretransmit: 0, partialack: 0, Second Congestion: 0), with data: 271222, total data bytes: 5154451
+
+ Packets received in fast path: 0, fast processed: 0, slow path: 0
+ fast lock acquisition failures: 0, slow path: 0
+TCP Semaphore      0x7F25402610C0  FREE 
\ No newline at end of file
diff --git a/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv4_unicast_neigh_3_3_3_3.txt b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv4_unicast_neigh_3_3_3_3.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv4_unicast_neigh_3_3_3_3.txt
@@ -0,0 +1,64 @@
+BGP neighbor is 3.3.3.3,  remote AS 3, external link
+ Description: Three
+ Administratively shut down
+  BGP version 4, remote router ID 0.0.0.0
+  BGP state = Idle
+  Neighbor sessions:
+    0 active, is not multisession capable (disabled)
+    Stateful switchover support enabled: NO
+  Do log neighbor state changes (via global configuration)
+  Default minimum time between advertisement runs is 30 seconds
+
+ For address family: IPv4 Unicast
+  BGP table version 64572104, neighbor version 1/64572104
+  Output queue size : 0
+  Index 0, Advertise bit 0
+  Inherits from template ebgp-peer
+  Inbound soft reconfiguration allowed
+  My AS number is allowed for 10 number of times
+  NEXT_HOP is always this router for eBGP paths
+  Community attribute sent to this neighbor
+  Extended-community attribute sent to this neighbor
+  Inbound path policy configured
+  Outbound path policy configured
+  Incoming update prefix filter list is bogons-in
+  Outgoing update prefix filter list is BGP_TO_TRANSIT
+  Route map for incoming advertisements is bgp-in
+  Route map for outgoing advertisements is bgp-out
+  Slow-peer detection is disabled
+  Slow-peer split-update-group dynamic is disabled
+                                 Sent       Rcvd
+  Prefix activity:               ----       ----
+    Prefixes Current:               0          0
+    Prefixes Total:                 0          0
+    Implicit Withdraw:              0          0
+    Explicit Withdraw:              0          0
+    Used as bestpath:             n/a          0
+    Used as multipath:            n/a          0
+    Used as secondary:            n/a          0
+
+                                   Outbound    Inbound
+  Local Policy Denied Prefixes:    --------    -------
+    Total:                                0          0
+  Number of NLRIs in the update sent: max 0, min 0
+  Last detected as dynamic slow peer: never
+  Dynamic slow peer recovered: never
+  Refresh Epoch: 1
+  Last Sent Refresh Start-of-rib: never
+  Last Sent Refresh End-of-rib: never
+  Last Received Refresh Start-of-rib: never
+  Last Received Refresh End-of-rib: never
+				       Sent	  Rcvd
+	Refresh activity:	       ----	  ----
+	  Refresh Start-of-RIB          0          0
+	  Refresh End-of-RIB            0          0
+
+  Address tracking is enabled, the RIB does have a route to 3.3.3.3
+  Connections established 0; dropped 0
+  Last reset never
+  External BGP neighbor configured for connected checks (single-hop no-disable-connected-check)
+  Interface associated: (none) (peering address NOT in same link)
+  Transport(tcp) path-mtu-discovery is enabled
+  Graceful-Restart is enabled, restart-time 120 seconds, stalepath-time 360 seconds
+  SSO is disabled
+  No active TCP connection
\ No newline at end of file
diff --git a/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv6_unicast_neigh_2001_559__1.txt b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv6_unicast_neigh_2001_559__1.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_ipv6_unicast_neigh_2001_559__1.txt
@@ -0,0 +1,128 @@
+
+BGP neighbor is 2001:559::1,  remote AS 7922, external link
+ Description: Comcast IPv6 Transit
+ Inherits from template PEER-SESSION-AS7922 for session parameters
+  BGP version 4, remote router ID 68.86.1.1
+  BGP state = Established, up for 12w2d
+  Last read 00:00:01, last write 00:00:35, hold time is 180, keepalive interval is 60 seconds
+  Neighbor sessions:
+    1 active, is not multisession capable (disabled)
+  Neighbor capabilities:
+    Route refresh: advertised and received(new)
+    Four-octets ASN Capability: advertised and received
+    Address family IPv6 Unicast: advertised and received
+    Graceful Restart Capability: advertised and received
+      Remote Restart timer is 120 seconds
+      Address families advertised by peer:
+        IPv6 Unicast (was preserved
+    Enhanced Refresh Capability: advertised
+    Multisession Capability: 
+    Stateful switchover support enabled: NO for session 1
+  Message statistics:
+    InQ depth is 0
+    OutQ depth is 0
+    
+                         Sent       Rcvd
+    Opens:                  1          1
+    Notifications:          0          0
+    Updates:             2480    6974616
+    Keepalives:        136309         69
+    Route Refresh:          0          0
+    Total:             138790    6974686
+  Do log neighbor state changes (via global configuration)
+  Default minimum time between advertisement runs is 30 seconds
+
+ For address family: IPv6 Unicast
+  Session: 2001:559::1
+  BGP table version 117061141, neighbor version 117061129/117061141
+  Output queue size : 0
+  Index 1, Advertise bit 0
+  1 update-group member
+  Inherits from template PEER-POLICY-COMCAST-IPv6
+  My AS number is allowed for 10 number of times
+  NEXT_HOP is always this router for eBGP paths
+  Inbound path policy configured
+  Outbound path policy configured
+  Incoming update prefix filter list is BGP-BOGONS-IPv6-IN
+  Outgoing update prefix filter list is BGP-TRANSIT-IPv6-OUT
+  Route map for incoming advertisements is BGP-COMCAST-IPv6-IN
+  Route map for outgoing advertisements is BGP-TRANSIT-IPv6-OUT
+  Slow-peer detection is disabled
+  Slow-peer split-update-group dynamic is disabled
+                                 Sent       Rcvd
+  Prefix activity:               ----       ----
+    Prefixes Current:               2      45717 (Consumes 6948984 bytes)
+    Prefixes Total:              4958    8328487
+    Implicit Withdraw:           4956    7470835
+    Explicit Withdraw:              0     811935
+    Used as bestpath:             n/a      45715
+    Used as multipath:            n/a          0
+    Used as secondary:            n/a          0
+
+                                   Outbound    Inbound
+  Local Policy Denied Prefixes:    --------    -------
+    Other Policies:               112415977        n/a
+    Total:                        112415977          0
+  Number of NLRIs in the update sent: max 2, min 0
+  Last detected as dynamic slow peer: never
+  Dynamic slow peer recovered: never
+  Refresh Epoch: 1
+  Last Sent Refresh Start-of-rib: never
+  Last Sent Refresh End-of-rib: never
+  Last Received Refresh Start-of-rib: never
+  Last Received Refresh End-of-rib: never
+				       Sent	  Rcvd
+	Refresh activity:	       ----	  ----
+	  Refresh Start-of-RIB          0          0
+	  Refresh End-of-RIB            0          0
+
+  Address tracking is enabled, the RIB does have a route to 2001:559::1
+  Connections established 1; dropped 0
+  Last reset never
+  External BGP neighbor configured for connected checks (single-hop no-disable-connected-check)
+  Interface associated: GigabitEthernet0/0/4 (peering address in same link)
+  Transport(tcp) path-mtu-discovery is enabled
+  Graceful-Restart is enabled, restart-time 120 seconds, stalepath-time 360 seconds
+  SSO is disabled
+Connection state is ESTAB, I/O status: 1, unread input bytes: 0            
+Connection is ECN Disabled, Mininum incoming TTL 0, Outgoing TTL 1
+Local host: 2001:559::2, Local port: 21958
+Foreign host: 2001:559::1, Foreign port: 179
+Connection tableid (VRF): 0
+Maximum output segment queue size: 50
+
+Enqueued packets for retransmit: 0, input: 0  mis-ordered: 0 (0 bytes)
+
+Event Timers (current time is 0x1BED85262):
+Timer          Starts    Wakeups            Next
+Retrans        138767          0             0x0
+TimeWait            0          0             0x0
+AckHold       2425311    1956394             0x0
+SendWnd             0          0             0x0
+KeepAlive           0          0             0x0
+GiveUp              0          0             0x0
+PmtuAger      7470660    7470659     0x1BED853C2
+DeadWait            0          0             0x0
+Linger              0          0             0x0
+ProcessQ            0          0             0x0
+
+iss: 3500006922  snduna: 3502837353  sndnxt: 3502837353
+irs: 2409182929  rcvnxt: 3188305548
+
+sndwnd:  65022  scale:      0  maxrcvwnd:  16384
+rcvwnd:  16164  scale:      0  delrcvwnd:    220
+
+SRTT: 1000 ms, RTTO: 1003 ms, RTV: 3 ms, KRTT: 0 ms
+minRTT: 1 ms, maxRTT: 1000 ms, ACK hold: 200 ms
+uptime: -1 ms, Sent idletime: 1099 ms, Receive idletime: 1299 ms 
+Status Flags: active open
+Option Flags: nagle, path mtu capable
+IP Precedence value : 6
+
+Datagrams (max data segment is 1440 bytes):
+Rcvd: 2561857 (out of order: 0), with data: 2431970, total data bytes: 779122618
+Sent: 2570215 (retransmit: 0, fastretransmit: 0, partialack: 0, Second Congestion: 0), with data: 2570215, total data bytes: 105639038
+
+ Packets received in fast path: 0, fast processed: 0, slow path: 0
+ fast lock acquisition failures: 0, slow path: 0
+TCP Semaphore      0x7F2543BB2160  FREE 
\ No newline at end of file
diff --git a/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_vpnv4_all_neigh_169_255_22_1.txt b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_vpnv4_all_neigh_169_255_22_1.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_bgp_neighbors_detail/normal/show_ip_bgp_vpnv4_all_neigh_169_255_22_1.txt
@@ -0,0 +1,128 @@
+
+BGP neighbor is 169.255.22.1,  vrf internal,  remote AS 1, internal link
+ Member of peer-group INTERNAL-GRE for session parameters
+  BGP version 4, remote router ID 10.87.121.3
+  BGP state = Established, up for 9w0d
+  Last read 00:00:45, last write 00:00:44, hold time is 180, keepalive interval is 60 seconds
+  Neighbor sessions:
+    1 active, is not multisession capable (disabled)
+  Neighbor capabilities:
+    Route refresh: advertised and received(new)
+    Four-octets ASN Capability: advertised and received
+    Address family IPv4 Unicast: advertised and received
+    Graceful Restart Capability: advertised and received
+      Remote Restart timer is 120 seconds
+      Address families advertised by peer:
+        IPv4 Unicast (was not preserved
+    Enhanced Refresh Capability: advertised and received
+    Multisession Capability: 
+    Stateful switchover support enabled: NO for session 1
+  Message statistics:
+    InQ depth is 0
+    OutQ depth is 0
+    
+                         Sent       Rcvd
+    Opens:                  1          1
+    Notifications:          0          0
+    Updates:                3       1748
+    Keepalives:        101259     100835
+    Route Refresh:          0          0
+    Total:             101263     102588
+  Do log neighbor state changes (via global configuration)
+  Default minimum time between advertisement runs is 0 seconds
+
+ For address family: VPNv4 Unicast
+  Translates address family IPv4 Unicast for VRF internal
+  Session: 169.255.22.1
+  BGP table version 6700, neighbor version 6700/0
+  Output queue size : 0
+  Index 7, Advertise bit 0
+  7 update-group member
+  ORD-GRE peer-group member
+  Inbound soft reconfiguration allowed
+  NEXT_HOP is always this router for eBGP paths
+  Inbound path policy configured
+  Outbound path policy configured
+  Route map for incoming advertisements is receive-from-internal
+  Route map for outgoing advertisements is announce-to-internal
+  Slow-peer detection is disabled
+  Slow-peer split-update-group dynamic is disabled
+                                 Sent       Rcvd
+  Prefix activity:               ----       ----
+    Prefixes Current:               7        440 (Consumes 181152 bytes)
+    Prefixes Total:                 7       2356
+    Implicit Withdraw:              0        962
+    Explicit Withdraw:              0        954
+    Used as bestpath:             n/a        880
+    Used as multipath:            n/a          0
+    Used as secondary:            n/a          0
+    Saved (soft-reconfig):        n/a        452 (Consumes 61472 bytes)
+
+                                   Outbound    Inbound
+  Local Policy Denied Prefixes:    --------    -------
+    route-map:                            0         39
+    Other Policies:                    1916        n/a
+    Total:                             1916         39
+  Number of NLRIs in the update sent: max 6, min 0
+  Last detected as dynamic slow peer: never
+  Dynamic slow peer recovered: never
+  Refresh Epoch: 3
+  Last Sent Refresh Start-of-rib: never
+  Last Sent Refresh End-of-rib: never
+  Last Received Refresh Start-of-rib: 3w1d
+  Last Received Refresh End-of-rib: 3w1d
+  Refresh-In took 0 seconds
+				       Sent	  Rcvd
+	Refresh activity:	       ----	  ----
+	  Refresh Start-of-RIB          0          2
+	  Refresh End-of-RIB            0          2
+
+  Address tracking is enabled, the RIB does have a route to 169.255.22.1
+  Connections established 4; dropped 3
+  Last reset 9w0d, due to Active open failed
+  Interface associated: (none) (peering address in same link)
+  Transport(tcp) path-mtu-discovery is enabled
+  Graceful-Restart is enabled, restart-time 120 seconds, stalepath-time 360 seconds
+  SSO is disabled
+Connection state is ESTAB, I/O status: 1, unread input bytes: 0            
+Connection is ECN Disabled, Mininum incoming TTL 0, Outgoing TTL 255
+Local host: 169.255.22.2, Local port: 50308
+Foreign host: 169.255.22.1, Foreign port: 179
+Connection tableid (VRF): 2
+Maximum output segment queue size: 50
+
+Enqueued packets for retransmit: 0, input: 0  mis-ordered: 0 (0 bytes)
+
+Event Timers (current time is 0x1BEDAC879):
+Timer          Starts    Wakeups            Next
+Retrans        101272         11             0x0
+TimeWait            0          0             0x0
+AckHold        102250     100245             0x0
+SendWnd             0          0             0x0
+KeepAlive           0          0             0x0
+GiveUp              0          0             0x0
+PmtuAger      5501240    5501239     0x1BEDACAEC
+DeadWait            0          0             0x0
+Linger              0          0             0x0
+ProcessQ            0          0             0x0
+
+iss: 1583292073  snduna: 1585216215  sndnxt: 1585216215
+irs: 1621912811  rcvnxt: 1623930253
+
+sndwnd:  15643  scale:      0  maxrcvwnd:  16384
+rcvwnd:  15092  scale:      0  delrcvwnd:   1292
+
+SRTT: 1000 ms, RTTO: 1003 ms, RTV: 3 ms, KRTT: 0 ms
+minRTT: 16 ms, maxRTT: 1000 ms, ACK hold: 200 ms
+uptime: -1 ms, Sent idletime: 44365 ms, Receive idletime: 44149 ms 
+Status Flags: active open
+Option Flags: VRF id set, nagle, path mtu capable
+IP Precedence value : 6
+
+Datagrams (max data segment is 1436 bytes):
+Rcvd: 203396 (out of order: 0), with data: 102528, total data bytes: 2017441
+Sent: 203183 (retransmit: 11, fastretransmit: 0, partialack: 0, Second Congestion: 0), with data: 101261, total data bytes: 1924141
+
+ Packets received in fast path: 0, fast processed: 0, slow path: 0
+ fast lock acquisition failures: 0, slow path: 0
+TCP Semaphore      0x7F2543BB1A10  FREE 
diff --git a/test/ios/utils/textfsm_templates/ip_bgp_all_sum.tpl b/test/ios/utils/textfsm_templates/ip_bgp_all_sum.tpl
new file mode 100644
--- /dev/null
+++ b/test/ios/utils/textfsm_templates/ip_bgp_all_sum.tpl
@@ -0,0 +1,24 @@
+Value Filldown ADDR_FAMILY (.*)
+Value Filldown ROUTER_ID (\S+)
+Value Filldown LOCAL_AS (\d+)
+Value NEIGHBOR (\S+)
+Value BGP_VER (\d)
+Value REMOTE_AS (\d+)
+Value MSG_RECV (\d+)
+Value MSG_SENT (\d+)
+Value TBL_VER (\d+)
+Value IN_Q (\d+)
+Value OUT_Q (\d+)
+Value UP (\w+)
+Value PREFIX_RECV (.*)
+
+Start
+  ^For address family\: ${ADDR_FAMILY}
+  ^BGP router identifier ${ROUTER_ID}, local AS number ${LOCAL_AS}
+  ^Neighbor\s+V -> Table
+
+Table
+  ^${NEIGHBOR}\s+${BGP_VER}\s+${REMOTE_AS}\s+${MSG_RECV}\s+${MSG_SENT}\s+${TBL_VER}\s+${IN_Q}\s+${OUT_Q}\s+${UP}\s+${PREFIX_RECV} -> Record Table
+  ^\s* -> Clearall Start
+
+EOF
diff --git a/test/ios/utils/textfsm_templates/ip_bgp_neigh.tpl b/test/ios/utils/textfsm_templates/ip_bgp_neigh.tpl
new file mode 100644
--- /dev/null
+++ b/test/ios/utils/textfsm_templates/ip_bgp_neigh.tpl
@@ -0,0 +1,56 @@
+Value NEIGHBOR (\S+)
+Value REMOTE_AS (\d+)
+Value BGP_TYPE (\w+)
+Value VRF (\w+)
+Value DESCRIPTION (.*)
+Value ROUTER_ID (\S+)
+Value BGP_STATE (\w+)
+Value UP (\w+)
+Value UPTIME (\w+)
+Value LAST_READ (.*)
+Value LAST_WRITE (.*)
+Value HOLDTIME (\d+)
+Value KEEPALIVE (\d+)
+Value FOUR_BYTE_AS (.*)
+Value MSG_OPEN_OUT (\d+)
+Value MSG_OPEN_IN (\d+)
+Value MSG_NOTI_OUT (\d+)
+Value MSG_NOTI_IN (\d+)
+Value MSG_UPDATE_OUT (\d+)
+Value MSG_UPDATE_IN (\d+)
+Value MSG_KEEPALIVE_OUT (\d+)
+Value MSG_KEEPALIVE_IN (\d+)
+Value MSG_REFRESH_OUT (\d+)
+Value MSG_REFRESH_IN (\d+)
+Value MSG_TOTAL_OUT (\d+)
+Value MSG_TOTAL_IN (\d+)
+Value LOCAL_ADDRESS (.*)
+Value LOCAL_PORT (\d+)
+Value REMOTE_ADDRESS (.*)
+Value REMOTE_PORT (\d+)
+Value ROUTING_TABLE (\d+)
+Value CONN_STATE (\w+)
+
+Start
+  ^BGP neighbor is ${NEIGHBOR},(?:\s+vrf ${VRF},)?\s+remote AS\s+${REMOTE_AS},\s+${BGP_TYPE} link
+  ^\s+Administratively shut ${UP}
+  ^\s+Description:\s+${DESCRIPTION}
+  ^\s+BGP version 4, remote router ID ${ROUTER_ID}
+  ^\s+BGP state = ${BGP_STATE}(?:, ${UP} for ${UPTIME})?
+  ^\s+Last read ${LAST_READ}, last write ${LAST_WRITE}, hold time is ${HOLDTIME}, keepalive interval is ${KEEPALIVE} seconds
+  ^\s+Four-octets ASN Capability:\s+${FOUR_BYTE_AS}
+  ^\s+Opens:\s+${MSG_OPEN_OUT}\s+${MSG_OPEN_IN}
+  ^\s+Notifications:\s+${MSG_NOTI_OUT}\s+${MSG_NOTI_IN}
+  ^\s+Updates:\s+${MSG_UPDATE_OUT}\s+${MSG_UPDATE_IN}
+  ^\s+Keepalives:\s+${MSG_KEEPALIVE_OUT}\s+${MSG_KEEPALIVE_IN}
+  ^\s+Route Refresh:\s+${MSG_REFRESH_OUT}\s+${MSG_REFRESH_IN}
+  ^\s+Total:\s+${MSG_TOTAL_OUT}\s+${MSG_TOTAL_IN}
+  ^\s*Connection state is ${CONN_STATE},
+  ^\s*For address family -> Afi
+  ^Local host: ${LOCAL_ADDRESS}, Local port: ${LOCAL_PORT}
+  ^Foreign host: ${REMOTE_ADDRESS}, Foreign port: ${REMOTE_PORT}
+  ^Connection tableid \(VRF\): ${ROUTING_TABLE}
+
+Afi
+  ^\s -> Next
+  ^\w -> Start
\ No newline at end of file
diff --git a/test/ios/utils/textfsm_templates/ip_bgp_neigh_afi.tpl b/test/ios/utils/textfsm_templates/ip_bgp_neigh_afi.tpl
new file mode 100644
--- /dev/null
+++ b/test/ios/utils/textfsm_templates/ip_bgp_neigh_afi.tpl
@@ -0,0 +1,41 @@
+Value AFI (.*)
+Value SESSION (\S+)
+Value POLICY_IN (\S+)
+Value POLICY_OUT (\S+)
+Value PREFIX_CURR_OUT (\d+)
+Value PREFIX_CURR_IN (\d+)
+Value PREFIX_TOTAL_OUT (\d+)
+Value PREFIX_TOTAL_IN (\d+)
+Value WITHDRAW_IMPLICIT_OUT (\d+)
+Value WITHDRAW_IMPLICIT_IN (\d+)
+Value WITHDRAW_EXPLICIT_OUT (\d+)
+Value WITHDRAW_EXPLICIT_IN (\d+)
+Value BESTPATHS (\d+)
+Value MULTIPATHS (\d+)
+Value SECONDARIES (\d+)
+Value REJECTED_PREFIX_IN (\d+)
+Value REJECTED_PREFIX_OUT (\d+)
+Value FLAP_COUNT (\d+)
+Value LAST_EVENT (.*)
+Value LOCAL_ADDR_CONF (peering address in same link)
+
+Start
+  ^\s*For address family: -> Continue.Record
+  ^\s*For address family: ${AFI}
+  ^\s+Session: ${SESSION}
+  ^\s+Route map for incoming advertisements is ${POLICY_IN}
+  ^\s+Route map for outgoing advertisements is ${POLICY_OUT}
+  ^\s+Prefixes Current:\s+${PREFIX_CURR_OUT}\s+${PREFIX_CURR_IN}
+  ^\s+Prefixes Total:\s+${PREFIX_TOTAL_OUT}\s+${PREFIX_TOTAL_IN}
+  ^\s+Implicit Withdraw:\s+${WITHDRAW_IMPLICIT_OUT}\s+${WITHDRAW_IMPLICIT_IN}
+  ^\s+Explicit Withdraw:\s+${WITHDRAW_EXPLICIT_OUT}\s+${WITHDRAW_EXPLICIT_IN}
+  ^\s+Used as bestpath:\s+\S+\s+${BESTPATHS}
+  ^\s+Used as multipath:\s+\S+\s+${MULTIPATHS}
+  ^\s+Used as secondary:\s+\S+\s+${SECONDARIES}
+  ^\s+Total:\s+${REJECTED_PREFIX_OUT}\s+${REJECTED_PREFIX_IN}
+  ^\s+Connections established\s+\d+;\s+dropped\s+${FLAP_COUNT}
+  ^\s+Last reset ${LAST_EVENT}
+  ^\s+Interface associated: \S+ \(${LOCAL_ADDR_CONF}\)
+  ^Connection state is -> Record
+
+  
\ No newline at end of file