BGP neighbor information.

        Currently no VRF support. Supports both IPv4 and IPv6.
162219
def get_bgp_neighbors(self):
        
        supported_afi = ['ipv4', 'ipv6']

        bgp_neighbor_data = dict()
        bgp_neighbor_data['global'] = {}

        # get summary output from device
        cmd_bgp_all_sum = 'show bgp all summary'
        summary_output = self._send_command(cmd_bgp_all_sum).strip()

        # get neighbor output from device
        neighbor_output = ''
        for afi in supported_afi:
            cmd_bgp_neighbor = 'show bgp %s unicast neighbors' % afi
            neighbor_output += self._send_command(cmd_bgp_neighbor).strip()
            # trailing newline required for parsing
            neighbor_output += "\n"

        # Regular expressions used for parsing BGP summary
        parse_summary = {
            'patterns': [
                # For address family: IPv4 Unicast
                {'regexp': re.compile(r'^For address family: (?P<afi>\S+) '),
                 'record': False},
                # Capture router_id and local_as values, e.g.:
                # BGP router identifier 10.0.1.1, local AS number 65000
                {'regexp': re.compile(r'^.* router identifier (?P<router_id>{}), '
                                      r'local AS number (?P<local_as>{})'.format(
                                            IPV4_ADDR_REGEX, ASN_REGEX
                                      )),
                 'record': False},
                # Match neighbor summary row, capturing useful details and
                # discarding the 5 columns that we don't care about, e.g.:
                # Neighbor   V          AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
                # 10.0.0.2   4       65000 1336020 64337701 1011343614    0    0 8w0d         3143
                {'regexp': re.compile(r'^\*?(?P<remote_addr>({})|({}))'
                                      r'\s+\d+\s+(?P<remote_as>{})(\s+\S+){{5}}\s+'
                                      r'(?P<uptime>(never)|\d+\S+)'
                                      r'\s+(?P<accepted_prefixes>\d+)'.format(
                                            IPV4_ADDR_REGEX, IPV6_ADDR_REGEX, ASN_REGEX
                                      )),
                 'record': True},
                # Same as above, but for peer that are not Established, e.g.:
                # Neighbor      V       AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
                # 192.168.0.2   4    65002       0       0        1    0    0 never    Active
                {'regexp': re.compile(r'^\*?(?P<remote_addr>({})|({}))'
                                      r'\s+\d+\s+(?P<remote_as>{})(\s+\S+){{5}}\s+'
                                      r'(?P<uptime>(never)|\d+\S+)\s+(?P<state>\D.*)'.format(
                                            IPV4_ADDR_REGEX, IPV6_ADDR_REGEX, ASN_REGEX
                                      )),
                 'record': True},
                # ipv6 peers often break accross rows because of the longer peer address,
                # match as above, but in separate expressions, e.g.:
                # Neighbor      V       AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
                # 2001:DB8::4
                #               4    65004 9900690  612449 155362939    0    0 26w6d       36391
                {'regexp': re.compile(r'^\*?(?P<remote_addr>({})|({}))'.format(
                                            IPV4_ADDR_REGEX, IPV6_ADDR_REGEX
                                     )),
                 'record': False},
                {'regexp': re.compile(r'^\s+\d+\s+(?P<remote_as>{})(\s+\S+){{5}}\s+'
                                      r'(?P<uptime>(never)|\d+\S+)'
                                      r'\s+(?P<accepted_prefixes>\d+)'.format(
                                            ASN_REGEX
                                      )),
                 'record': True},
                # Same as above, but for peers that are not Established, e.g.:
                # Neighbor      V       AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
                # 2001:DB8::3
                #               4    65003       0       0        1    0    0 never    Idle (Admin)
                {'regexp': re.compile(r'^\s+\d+\s+(?P<remote_as>{})(\s+\S+){{5}}\s+'
                                      r'(?P<uptime>(never)|\d+\S+)\s+(?P<state>\D.*)'.format(
                                            ASN_REGEX
                                      )),
                 'record': True}
            ],
            'no_fill_fields': ['accepted_prefixes', 'state', 'uptime', 'remote_as', 'remote_addr']
        }

        parse_neighbors = {
            'patterns': [
                # Capture BGP neighbor is 10.0.0.2,  remote AS 65000, internal link
                {'regexp': re.compile(r'^BGP neighbor is (?P<remote_addr>({})|({})),'
                                      r'\s+remote AS (?P<remote_as>{}).*'.format(
                                            IPV4_ADDR_REGEX, IPV6_ADDR_REGEX, ASN_REGEX
                                      )),
                 'record': False},
                # Capture description
                {'regexp': re.compile(r'^\s+Description: (?P<description>.+)'),
                 'record': False},
                # Capture remote_id, e.g.:
                # BGP version 4, remote router ID 10.0.1.2
                {'regexp': re.compile(r'^\s+BGP version \d+, remote router ID '
                                      r'(?P<remote_id>{})'.format(IPV4_ADDR_REGEX)),
                 'record': False},
                # Capture AFI and SAFI names, e.g.:
                # For address family: IPv4 Unicast
                {'regexp': re.compile(r'^\s+For address family: (?P<afi>\S+) '),
                 'record': False},
                # Capture current sent and accepted prefixes, e.g.:
                #     Prefixes Current:          637213       3142 (Consumes 377040 bytes)
                {'regexp': re.compile(r'^\s+Prefixes Current:\s+(?P<sent_prefixes>\d+)\s+'
                                      r'(?P<accepted_prefixes>\d+).*'),
                 'record': False},
                # Capture received_prefixes if soft-reconfig is enabled for the peer
                {'regexp': re.compile(r'^\s+Saved (soft-reconfig):.+(?P<received_prefixes>\d+).*'),
                 'record': True},
                # Otherwise, use the following as an end of row marker
                {'regexp': re.compile(r'^\s+Local Policy Denied Prefixes:.+'),
                 'record': True}
            ],
            # fields that should not be "filled down" across table rows
            'no_fill_fields': ['received_prefixes', 'accepted_prefixes', 'sent_prefixes']
        }

        # Parse outputs into a list of dicts
        summary_data = []
        summary_data_entry = {}

        for line in summary_output.splitlines():
            # check for matches against each pattern
            for item in parse_summary['patterns']:
                match = item['regexp'].match(line)
                if match:
                    # a match was found, so update the temp entry with the match's groupdict
                    summary_data_entry.update(match.groupdict())
                    if item['record']:
                        # Record indicates the last piece of data has been obtained; move
                        # on to next entry
                        summary_data.append(copy.deepcopy(summary_data_entry))
                        # remove keys that are listed in no_fill_fields before the next pass
                        for field in parse_summary['no_fill_fields']:
                            try:
                                del summary_data_entry[field]
                            except KeyError:
                                pass
                    break

        neighbor_data = []
        neighbor_data_entry = {}
        for line in neighbor_output.splitlines():
            # check for matches against each pattern
            for item in parse_neighbors['patterns']:
                match = item['regexp'].match(line)
                if match:
                    # a match was found, so update the temp entry with the match's groupdict
                    neighbor_data_entry.update(match.groupdict())
                    if item['record']:
                        # Record indicates the last piece of data has been obtained; move
                        # on to next entry
                        neighbor_data.append(copy.deepcopy(neighbor_data_entry))
                        # remove keys that are listed in no_fill_fields before the next pass
                        for field in parse_neighbors['no_fill_fields']:
                            try:
                                del neighbor_data_entry[field]
                            except KeyError:
                                pass
                    break

        router_id = None

        for entry in summary_data:
            if not router_id:
                router_id = entry['router_id']
            elif entry['router_id'] != router_id:
                raise ValueError

        # check the router_id looks like an ipv4 address
        router_id = napalm_base.helpers.ip(router_id, version=4)

        # add parsed data to output dict
        bgp_neighbor_data['global']['router_id'] = router_id
        bgp_neighbor_data['global']['peers'] = {}
        for entry in summary_data:
            remote_addr = napalm_base.helpers.ip(entry['remote_addr'])
            afi = entry['afi'].lower()
            # check that we're looking at a supported afi
            if afi not in supported_afi:
                continue
            # get neighbor_entry out of neighbor data
            neighbor_entry = None
            for neighbor in neighbor_data:
                if (neighbor['afi'].lower() == afi and
                        napalm_base.helpers.ip(neighbor['remote_addr']) == remote_addr):
                    neighbor_entry = neighbor
                    break
            if not isinstance(neighbor_entry, dict):
                raise ValueError(msg="Couldn't find neighbor data for %s in afi %s" %
                                     (remote_addr, afi))

            # check for admin down state
            try:
                if "(Admin)" in entry['state']:
                    is_enabled = False
                else:
                    is_enabled = True
            except KeyError:
                is_enabled = True

            # parse uptime value
            uptime = self.bgp_time_conversion(entry['uptime'])

            # Uptime should be -1 if BGP session not up
            is_up = True if uptime >= 0 else False

            # check whether session is up for address family and get prefix count
            try:
                accepted_prefixes = int(entry['accepted_prefixes'])
            except (ValueError, KeyError):
                accepted_prefixes = -1

            # Only parse neighbor detailed data if BGP session is-up
            if is_up:
                try:
                    # overide accepted_prefixes with neighbor data if possible (since that's newer)
                    accepted_prefixes = int(neighbor_entry['accepted_prefixes'])
                except (ValueError, KeyError):
                    pass

                # try to get received prefix count, otherwise set to accepted_prefixes
                received_prefixes = neighbor_entry.get('received_prefixes', accepted_prefixes)

                # try to get sent prefix count and convert to int, otherwise set to -1
                sent_prefixes = int(neighbor_entry.get('sent_prefixes', -1))
            else:
                received_prefixes = -1
                sent_prefixes = -1

            # get description
            try:
                description = py23_compat.text_type(neighbor_entry['description'])
            except KeyError:
                description = ''

            # check the remote router_id looks like an ipv4 address
            remote_id = napalm_base.helpers.ip(neighbor_entry['remote_id'], version=4)

            if remote_addr not in bgp_neighbor_data['global']['peers']:
                bgp_neighbor_data['global']['peers'][remote_addr] = {
                    'local_as': napalm_base.helpers.as_number(entry['local_as']),
                    'remote_as': napalm_base.helpers.as_number(entry['remote_as']),
                    'remote_id': remote_id,
                    'is_up': is_up,
                    'is_enabled': is_enabled,
                    'description': description,
                    'uptime': uptime,
                    'address_family': {
                        afi: {
                            'received_prefixes': received_prefixes,
                            'accepted_prefixes': accepted_prefixes,
                            'sent_prefixes': sent_prefixes
                        }
                    }
                }
            else:
                # found previous data for matching remote_addr, but for different afi
                existing = bgp_neighbor_data['global']['peers'][remote_addr]
                assert afi not in existing['address_family']
                # compare with existing values and croak if they don't match
                assert existing['local_as'] == napalm_base.helpers.as_number(entry['local_as'])
                assert existing['remote_as'] == napalm_base.helpers.as_number(entry['remote_as'])
                assert existing['remote_id'] == remote_id
                assert existing['is_enabled'] == is_enabled
                assert existing['description'] == description
                # merge other values in a sane manner
                existing['is_up'] = existing['is_up'] or is_up
                existing['uptime'] = max(existing['uptime'], uptime)
                existing['address_family'][afi] = {
                    'received_prefixes': received_prefixes,
                    'accepted_prefixes': accepted_prefixes,
                    'sent_prefixes': sent_prefixes
                }
        return bgp_neighbor_data
739403
public boolean isWellKnownIPv4Translatable() { //rfc 6052 rfc 6144
		//64:ff9b::/96 prefix for auto ipv4/ipv6 translation
		if(getSegment(0).matches(0x64) && getSegment(1).matches(0xff9b)) {
			for(int i=2; i<=5; i++) {
				if(!getSegment(i).isZero()) {
					return false;
				}
			}
			return true;
		}
		return false;
	}
237736
def ip4_address(self):
        
        if self._ip4_address is None and self.network is not None:
            self._ip4_address = self._get_ip_address(
                libvirt.VIR_IP_ADDR_TYPE_IPV4)

        return self._ip4_address
917215
function pton(af, addr, dest, index) {
  switch (af) {
    case IPV4_OCTETS:
      return pton4(addr, dest, index)
    case IPV6_OCTETS:
      return pton6(addr, dest, index)
    default:
      throw new Error('Unsupported ip address.')
  }
}
772637
def get_network_instances(self, name=""):
        """"""

        output = self._show_vrf()
        vrfs = {}
        all_vrf_interfaces = {}
        for vrf in output:
            if (
                vrf.get("route_distinguisher", "") == "<not set>"
                or vrf.get("route_distinguisher", "") == "None"
            ):
                vrf["route_distinguisher"] = ""
            else:
                vrf["route_distinguisher"] = py23_compat.text_type(
                    vrf["route_distinguisher"]
                )
            interfaces = {}
            for interface_raw in vrf.get("interfaces", []):
                interface = interface_raw.split(",")
                for line in interface:
                    if line.strip() != "":
                        interfaces[py23_compat.text_type(line.strip())] = {}
                        all_vrf_interfaces[py23_compat.text_type(line.strip())] = {}

            vrfs[py23_compat.text_type(vrf["name"])] = {
                "name": py23_compat.text_type(vrf["name"]),
                "type": "L3VRF",
                "state": {"route_distinguisher": vrf["route_distinguisher"]},
                "interfaces": {"interface": interfaces},
            }
        all_interfaces = self.get_interfaces_ip().keys()
        vrfs["default"] = {
            "name": "default",
            "type": "DEFAULT_INSTANCE",
            "state": {"route_distinguisher": ""},
            "interfaces": {
                "interface": {
                    k: {} for k in all_interfaces if k not in all_vrf_interfaces.keys()
                }
            },
        }

        if name:
            if name in vrfs:
                return {py23_compat.text_type(name): vrfs[name]}
            return {}
        else:
            return vrfs
112005
def add_ipv4addr(self, ipv4addr):
        
        for addr in self.ipv4addrs:
            if ((isinstance(addr, dict) and addr['ipv4addr'] == ipv4addr) or
                (isinstance(addr, HostIPv4) and addr.ipv4addr == ipv4addr)):
                raise ValueError('Already exists')
        self.ipv4addrs.append({'ipv4addr': ipv4addr})
459900
def get_bgp_neighbors(self):
        results = {}
        bgp_state_dict = {
            "Idle": {"is_up": False, "is_enabled": True},
            "Active": {"is_up": False, "is_enabled": True},
            "Open": {"is_up": False, "is_enabled": True},
            "Established": {"is_up": True, "is_enabled": True},
            "Closing": {"is_up": True, "is_enabled": True},
            "Shutdown": {"is_up": False, "is_enabled": False},
        }
        
        af_name_dict = {
            1: {1: "ipv4", 128: "vpnv4"},
            2: {1: "ipv6", 128: "vpnv6"},
            25: {70: "l2vpn"},
        }

        try:
            cmd = "show bgp all summary vrf all"
            vrf_list = self._get_command_table(cmd, "TABLE_vrf", "ROW_vrf")
        except NXAPICommandError:
            vrf_list = []

        for vrf_dict in vrf_list:
            result_vrf_dict = {
                "router_id": py23_compat.text_type(vrf_dict["vrf-router-id"]),
                "peers": {},
            }

            af_list = vrf_dict.get("TABLE_af", {}).get("ROW_af", [])
            if isinstance(af_list, dict):
                af_list = [af_list]

            for af_dict in af_list:
                saf_dict = af_dict.get("TABLE_saf", {}).get("ROW_saf", {})
                neighbors_list = saf_dict.get("TABLE_neighbor", {}).get(
                    "ROW_neighbor", []
                )

                if isinstance(neighbors_list, dict):
                    neighbors_list = [neighbors_list]

                for neighbor_dict in neighbors_list:
                    neighborid = napalm.base.helpers.ip(neighbor_dict["neighborid"])
                    remoteas = napalm.base.helpers.as_number(
                        neighbor_dict["neighboras"]
                    )
                    state = py23_compat.text_type(neighbor_dict["state"])

                    bgp_state = bgp_state_dict[state]
                    afid_dict = af_name_dict[int(af_dict["af-id"])]
                    safi_name = afid_dict[int(saf_dict["safi"])]

                    result_peer_dict = {
                        "local_as": int(vrf_dict["vrf-local-as"]),
                        "remote_as": remoteas,
                        "remote_id": neighborid,
                        "is_enabled": bgp_state["is_enabled"],
                        "uptime": -1,
                        "description": "",
                        "is_up": bgp_state["is_up"],
                        "address_family": {
                            safi_name: {
                                "sent_prefixes": -1,
                                "accepted_prefixes": -1,
                                "received_prefixes": int(
                                    neighbor_dict["prefixreceived"]
                                ),
                            }
                        },
                    }
                    result_vrf_dict["peers"][neighborid] = result_peer_dict

            vrf_name = vrf_dict["vrf-name-out"]
            if vrf_name == "default":
                vrf_name = "global"
            results[vrf_name] = result_vrf_dict
        return results
358490
def import_single_vpn_path_to_all_vrfs(self, vpn_path, path_rts=None):
        
        LOG.debug('Importing path %s to qualifying VRFs', vpn_path)

        # If this path has no RTs we are done.
        if not path_rts:
            LOG.info('Encountered a path with no RTs: %s', vpn_path)
            return

        # We match path RTs with all VRFs that are interested in them.
        interested_tables = set()

        # Get route family of VRF to when this VPN Path can be imported to
        if vpn_path.route_family == RF_IPv4_VPN:
            route_family = RF_IPv4_UC
        elif vpn_path.route_family == RF_IPv6_VPN:
            route_family = RF_IPv6_UC
        elif vpn_path.route_family == RF_L2_EVPN:
            route_family = RF_L2_EVPN
        elif vpn_path.route_family == RF_VPNv4_FLOWSPEC:
            route_family = RF_IPv4_FLOWSPEC
        elif vpn_path.route_family == RF_VPNv6_FLOWSPEC:
            route_family = RF_IPv6_FLOWSPEC
        elif vpn_path.route_family == RF_L2VPN_FLOWSPEC:
            route_family = RF_L2VPN_FLOWSPEC
        else:
            raise ValueError('Unsupported route family for VRF: %s' %
                             vpn_path.route_family)

        for rt in path_rts:
            rt_rf_id = rt + ':' + str(route_family)
            vrf_rt_tables = self._tables_for_rt.get(rt_rf_id)
            if vrf_rt_tables:
                interested_tables.update(vrf_rt_tables)

        if interested_tables:
            # We iterate over all VRF tables that are interested in the RT
            # of the given path and import this path into them.
            route_dist = vpn_path.nlri.route_dist
            for vrf_table in interested_tables:
                if (vpn_path.source is not None or
                        route_dist != vrf_table.vrf_conf.route_dist):
                    update_vrf_dest = vrf_table.import_vpn_path(vpn_path)
                    # Queue the destination for further processing.
                    if update_vrf_dest is not None:
                        self._signal_bus.\
                            dest_changed(update_vrf_dest)
        else:
            # If we do not have any VRF with import RT that match with path RT
            LOG.debug('No VRF table found that imports RTs: %s', path_rts)
1151248
private static boolean anyInterfaceSupportsIpV6() {
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface iface = interfaces.nextElement();
                Enumeration<InetAddress> addresses = iface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    if (addresses.nextElement() instanceof Inet6Address) {
                        return true;
                    }
                }
            }
        } catch (SocketException e) {
            logger.debug("Unable to detect if any interface supports IPv6, assuming IPv4-only", e);
            // ignore
        }
        return false;
    }
1186698
def on_update_enabled(self, conf_evt):
        
        enabled = conf_evt.value
        # If we do not have any protocol bound and configuration asks us to
        # enable this peer, we try to establish connection again.
        if enabled:
            LOG.info('%s enabled', self)
            if self._protocol and self._protocol.started:
                LOG.error('Tried to enable neighbor that is already enabled')
            else:
                self.state.bgp_state = const.BGP_FSM_CONNECT
                # Restart connect loop if not already running.
                if not self._connect_retry_event.is_set():
                    self._connect_retry_event.set()
                    LOG.debug('Starting connect loop as neighbor is enabled.')
        else:
            LOG.info('%s disabled', self)
            if self._protocol:
                # Stopping protocol will eventually trigger connection_lost
                # handler which will do some clean-up.
                # But the greenlet that is in charge of the socket may be kill
                # when we stop the protocol, hence we call connection_lost
                # here as we triggered socket to close.
                self._protocol.send_notification(
                    BGP_ERROR_CEASE,
                    BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN
                )
                self._protocol.stop()
                self._protocol = None
                self.state.bgp_state = const.BGP_FSM_IDLE
            # If this peer is not enabled any-more we stop trying to make any
            # connection.
            LOG.debug('Disabling connect-retry as neighbor was disabled')
            self._connect_retry_event.clear()
787114
def _has_ipv6(host):
    
    sock = None
    has_ipv6 = False

    # App Engine doesn't support IPV6 sockets and actually has a quota on the
    # number of sockets that can be used, so just early out here instead of
    # creating a socket needlessly.
    # See https://github.com/urllib3/urllib3/issues/1446
    if _appengine_environ.is_appengine_sandbox():
        return False

    if socket.has_ipv6:
        # has_ipv6 returns true if cPython was compiled with IPv6 support.
        # It does not tell us if the system has IPv6 support enabled. To
        # determine that we must bind to an IPv6 address.
        # https://github.com/shazow/urllib3/pull/611
        # https://bugs.python.org/issue658327
        try:
            sock = socket.socket(socket.AF_INET6)
            sock.bind((host, 0))
            has_ipv6 = True
        except Exception:
            pass

    if sock:
        sock.close()
    return has_ipv6
44823
def get_neighbors( self, peer_hostport, con=None, path=None, peer_table=None ):
        
        if path is None:
            path = self.atlasdb_path

        if self.neighbors_timeout is None:
            self.neighbors_timeout = atlas_neighbors_timeout()
 
        peer_hostport = self.canonical_peer( peer_hostport )

        neighbors = None
        if peer_hostport == self.my_hostport:
            neighbors = atlas_get_live_neighbors( None, peer_table=peer_table ) 
        else:
            neighbors = atlas_peer_get_neighbors( self.my_hostport, peer_hostport, timeout=self.neighbors_timeout, peer_table=peer_table, path=path, con=con )

        if neighbors is not None:
            log.debug("%s: neighbors of %s are (%s): %s" % (self.my_hostport, peer_hostport, len(neighbors), ",".join(neighbors)))
        else:
            log.error("%s: failed to ask %s for neighbors" % (self.my_hostport, peer_hostport))

        return neighbors
153821
def add_vrf(self):
        

        v = VRF()
        if 'rt' in request.json:
            v.rt = validate_string(request.json, 'rt')
        if 'name' in request.json:
            v.name = validate_string(request.json, 'name')
        if 'description' in request.json:
            v.description = validate_string(request.json, 'description')
        if 'tags' in request.json:
            v.tags = request.json['tags']
        if 'avps' in request.json:
            v.avps = request.json['avps']

        try:
            v.save()
        except NipapError, e:
            return json.dumps({'error': 1, 'message': e.args, 'type': type(e).__name__})

        return json.dumps(v, cls=NipapJSONEncoder)
836851
public boolean isIPv4Mapped() {
		//::ffff:x:x/96 indicates IPv6 address mapped to IPv4
		if(getSegment(5).matches(IPv6Address.MAX_VALUE_PER_SEGMENT)) {
			for(int i = 0; i < 5; i++) {
				if(!getSegment(i).isZero()) {
					return false;
				}
			}
			return true;
		}
		return false;
	}
34916
def create(self, neighbors):
        

        data = {'neighbors': neighbors}
        return super(ApiV4Neighbor, self).post('api/v4/neighbor/', data)
1065273
def get_bgp_config(self, group="", neighbor=""):
        """"""
        _GROUP_FIELD_MAP_ = {
            "type": "type",
            "multipath": "multipath",
            "apply-groups": "apply_groups",
            "remove-private-as": "remove_private_as",
            "ebgp-multihop": "multihop_ttl",
            "remote-as": "remote_as",
            "local-v4-addr": "local_address",
            "local-v6-addr": "local_address",
            "local-as": "local_as",
            "description": "description",
            "import-policy": "import_policy",
            "export-policy": "export_policy",
        }

        _PEER_FIELD_MAP_ = {
            "description": "description",
            "remote-as": "remote_as",
            "local-v4-addr": "local_address",
            "local-v6-addr": "local_address",
            "local-as": "local_as",
            "next-hop-self": "nhs",
            "route-reflector-client": "route_reflector_client",
            "import-policy": "import_policy",
            "export-policy": "export_policy",
            "passwd": "authentication_key",
        }

        _PROPERTY_FIELD_MAP_ = _GROUP_FIELD_MAP_.copy()
        _PROPERTY_FIELD_MAP_.update(_PEER_FIELD_MAP_)

        _PROPERTY_TYPE_MAP_ = {
            # used to determine the default value
            # and cast the values
            "remote-as": int,
            "ebgp-multihop": int,
            "local-v4-addr": py23_compat.text_type,
            "local-v6-addr": py23_compat.text_type,
            "local-as": int,
            "remove-private-as": bool,
            "next-hop-self": bool,
            "description": py23_compat.text_type,
            "route-reflector-client": bool,
            "password": py23_compat.text_type,
            "route-map": py23_compat.text_type,
            "apply-groups": list,
            "type": py23_compat.text_type,
            "import-policy": py23_compat.text_type,
            "export-policy": py23_compat.text_type,
            "multipath": bool,
        }

        _DATATYPE_DEFAULT_ = {py23_compat.text_type: "", int: 0, bool: False, list: []}

        def default_group_dict(local_as):
            group_dict = {}
            group_dict.update(
                {
                    key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop))
                    for prop, key in _GROUP_FIELD_MAP_.items()
                }
            )
            group_dict.update(
                {"prefix_limit": {}, "neighbors": {}, "local_as": local_as}
            )  # few more default values
            return group_dict

        def default_neighbor_dict(local_as):
            neighbor_dict = {}
            neighbor_dict.update(
                {
                    key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop))
                    for prop, key in _PEER_FIELD_MAP_.items()
                }
            )  # populating with default values
            neighbor_dict.update(
                {"prefix_limit": {}, "local_as": local_as, "authentication_key": ""}
            )  # few more default values
            return neighbor_dict

        def parse_options(options, default_value=False):

            if not options:
                return {}

            config_property = options[0]
            field_name = _PROPERTY_FIELD_MAP_.get(config_property)
            field_type = _PROPERTY_TYPE_MAP_.get(config_property)
            field_value = _DATATYPE_DEFAULT_.get(field_type)  # to get the default value

            if not field_type:
                # no type specified at all => return empty dictionary
                return {}

            if not default_value:
                if len(options) > 1:
                    field_value = napalm.base.helpers.convert(
                        field_type, options[1], _DATATYPE_DEFAULT_.get(field_type)
                    )
                else:
                    if field_type is bool:
                        field_value = True
            if field_name is not None:
                return {field_name: field_value}
            elif config_property in ["route-map", "password"]:
                # do not respect the pattern neighbor [IP_ADDRESS] [PROPERTY] [VALUE]
                # or need special output (e.g.: maximum-routes)
                if config_property == "password":
                    return {"authentication_key": py23_compat.text_type(options[2])}
                    # returns the MD5 password
                if config_property == "route-map":
                    direction = None
                    if len(options) == 3:
                        direction = options[2]
                        field_value = field_type(options[1])  # the name of the policy
                    elif len(options) == 2:
                        direction = options[1]
                    if direction == "in":
                        field_name = "import_policy"
                    else:
                        field_name = "export_policy"
                    return {field_name: field_value}

            return {}

        bgp_config = {}

        commands = ["show running-config | section router bgp"]
        bgp_conf = self.device.run_commands(commands, encoding="text")[0].get(
            "output", "\n\n"
        )
        bgp_conf_lines = bgp_conf.splitlines()

        bgp_neighbors = {}

        if not group:
            neighbor = ""  # noqa

        local_as = 0
        bgp_neighbors = {}
        for bgp_conf_line in bgp_conf_lines:
            default_value = False
            bgp_conf_line = bgp_conf_line.strip()
            if bgp_conf_line.startswith("router bgp"):
                local_as = int(bgp_conf_line.replace("router bgp", "").strip())
                continue
            if not (
                bgp_conf_line.startswith("neighbor")
                or bgp_conf_line.startswith("no neighbor")
            ):
                continue
            if bgp_conf_line.startswith("no"):
                default_value = True
            bgp_conf_line = bgp_conf_line.replace("no neighbor ", "").replace(
                "neighbor ", ""
            )
            bgp_conf_line_details = bgp_conf_line.split()
            group_or_neighbor = py23_compat.text_type(bgp_conf_line_details[0])
            options = bgp_conf_line_details[1:]
            try:
                # will try to parse the neighbor name
                # which sometimes is the IP Address of the neigbor
                # or the name of the BGP group
                IPAddress(group_or_neighbor)
                # if passes the test => it is an IP Address, thus a Neighbor!
                peer_address = group_or_neighbor
                if peer_address not in bgp_neighbors:
                    bgp_neighbors[peer_address] = default_neighbor_dict(local_as)
                if options[0] == "peer-group":
                    bgp_neighbors[peer_address]["__group"] = options[1]

                # in the config, neighbor details are lister after
                # the group is specified for the neighbor:
                #
                # neighbor 192.168.172.36 peer-group 4-public-anycast-peers
                # neighbor 192.168.172.36 remote-as 12392
                # neighbor 192.168.172.36 maximum-routes 200
                #
                # because the lines are parsed sequentially
                # can use the last group detected
                # that way we avoid one more loop to
                # match the neighbors with the group they belong to
                # directly will apend the neighbor in the neighbor list of the group at the end

                bgp_neighbors[peer_address].update(
                    parse_options(options, default_value)
                )
            except AddrFormatError:
                # exception trying to parse group name
                # group_or_neighbor represents the name of the group
                group_name = group_or_neighbor
                if group and group_name != group:
                    continue
                if group_name not in bgp_config.keys():
                    bgp_config[group_name] = default_group_dict(local_as)
                bgp_config[group_name].update(parse_options(options, default_value))

        for peer, peer_details in bgp_neighbors.items():
            peer_group = peer_details.pop("__group", None)
            if not peer_group:
                peer_group = "_"
            if peer_group not in bgp_config:
                bgp_config[peer_group] = default_group_dict(local_as)
            bgp_config[peer_group]["neighbors"][peer] = peer_details

        return bgp_config
1305352
def create_api_v4_neighbor(self):
        """"""
        return ApiV4Neighbor(
            self.networkapi_url,
            self.user,
            self.password,
            self.user_ldap)