Return BGP configuration.

def get_bgp_config(self, group="", neighbor=""):
        """Return BGP configuration."""

        def _check_nhs(policies, nhs_policies):
            if not isinstance(policies, list):
                # Make it a list if it is a single policy
                policies = [policies]
            # Return True if "next-hop self" was found in any of the policies p
            for p in policies:
                if nhs_policies[p] is True:
                    return True
            return False

        def update_dict(d, u):  # for deep dictionary update
            for k, v in u.items():
                if isinstance(d, collections.Mapping):
                    if isinstance(v, collections.Mapping):
                        r = update_dict(d.get(k, {}), v)
                        d[k] = r
                    else:
                        d[k] = u[k]
                else:
                    d = {k: u[k]}
            return d

        def build_prefix_limit(**args):
            """
            Transform the lements of a dictionary into nested dictionaries.

            Example:
                {
                    'inet_unicast_limit': 500,
                    'inet_unicast_teardown_threshold': 95,
                    'inet_unicast_teardown_timeout': 5
                }

                becomes:

                {
                    'inet': {
                        'unicast': {
                            'limit': 500,
                            'teardown': {
                                'threshold': 95,
                                'timeout': 5
                            }
                        }
                    }
                }
            """
            prefix_limit = {}

            for key, value in args.items():
                key_levels = key.split("_")
                length = len(key_levels) - 1
                temp_dict = {key_levels[length]: value}
                for index in reversed(range(length)):
                    level = key_levels[index]
                    temp_dict = {level: temp_dict}
                update_dict(prefix_limit, temp_dict)

            return prefix_limit

        _COMMON_FIELDS_DATATYPE_ = {
            "description": py23_compat.text_type,
            "local_address": py23_compat.text_type,
            "local_as": int,
            "remote_as": int,
            "import_policy": py23_compat.text_type,
            "export_policy": py23_compat.text_type,
            "inet_unicast_limit_prefix_limit": int,
            "inet_unicast_teardown_threshold_prefix_limit": int,
            "inet_unicast_teardown_timeout_prefix_limit": int,
            "inet_unicast_novalidate_prefix_limit": int,
            "inet_flow_limit_prefix_limit": int,
            "inet_flow_teardown_threshold_prefix_limit": int,
            "inet_flow_teardown_timeout_prefix_limit": int,
            "inet_flow_novalidate_prefix_limit": py23_compat.text_type,
            "inet6_unicast_limit_prefix_limit": int,
            "inet6_unicast_teardown_threshold_prefix_limit": int,
            "inet6_unicast_teardown_timeout_prefix_limit": int,
            "inet6_unicast_novalidate_prefix_limit": int,
            "inet6_flow_limit_prefix_limit": int,
            "inet6_flow_teardown_threshold_prefix_limit": int,
            "inet6_flow_teardown_timeout_prefix_limit": int,
            "inet6_flow_novalidate_prefix_limit": py23_compat.text_type,
        }

        _PEER_FIELDS_DATATYPE_MAP_ = {
            "authentication_key": py23_compat.text_type,
            "route_reflector_client": bool,
            "nhs": bool,
        }
        _PEER_FIELDS_DATATYPE_MAP_.update(_COMMON_FIELDS_DATATYPE_)

        _GROUP_FIELDS_DATATYPE_MAP_ = {
            "type": py23_compat.text_type,
            "apply_groups": list,
            "remove_private_as": bool,
            "multipath": bool,
            "multihop_ttl": int,
        }
        _GROUP_FIELDS_DATATYPE_MAP_.update(_COMMON_FIELDS_DATATYPE_)

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

        bgp_config = {}

        if group:
            bgp = junos_views.junos_bgp_config_group_table(self.device)
            bgp.get(group=group)
        else:
            bgp = junos_views.junos_bgp_config_table(self.device)
            bgp.get()
            neighbor = ""  # if no group is set, no neighbor should be set either
        bgp_items = bgp.items()

        if neighbor:
            neighbor_ip = napalm.base.helpers.ip(neighbor)

        # Get all policies configured in one go and check if "next-hop self" is found in each policy
        # Save the result in a dict indexed by policy name (junos policy-statement)
        # The value is a boolean. True if "next-hop self" was found
        # The resulting dict (nhs_policies) will be used by _check_nhs to determine if "nhs"
        # is configured or not in the policies applied to a BGP neighbor
        policy = junos_views.junos_policy_nhs_config_table(self.device)
        policy.get()
        nhs_policies = dict()
        for policy_name, is_nhs_list in policy.items():
            # is_nhs_list is a list with one element. Ex: [('is_nhs', True)]
            is_nhs, boolean = is_nhs_list[0]
            nhs_policies[policy_name] = boolean if boolean is not None else False

        for bgp_group in bgp_items:
            bgp_group_name = bgp_group[0]
            bgp_group_details = bgp_group[1]
            bgp_config[bgp_group_name] = {
                field: _DATATYPE_DEFAULT_.get(datatype)
                for field, datatype in _GROUP_FIELDS_DATATYPE_MAP_.items()
                if "_prefix_limit" not in field
            }
            for elem in bgp_group_details:
                if not ("_prefix_limit" not in elem[0] and elem[1] is not None):
                    continue
                datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(elem[0])
                default = _DATATYPE_DEFAULT_.get(datatype)
                key = elem[0]
                value = elem[1]
                if key in ["export_policy", "import_policy"]:
                    if isinstance(value, list):
                        value = " ".join(value)
                if key == "local_address":
                    value = napalm.base.helpers.convert(
                        napalm.base.helpers.ip, value, value
                    )
                if key == "neighbors":
                    bgp_group_peers = value
                    continue
                bgp_config[bgp_group_name].update(
                    {key: napalm.base.helpers.convert(datatype, value, default)}
                )
            prefix_limit_fields = {}
            for elem in bgp_group_details:
                if "_prefix_limit" in elem[0] and elem[1] is not None:
                    datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(elem[0])
                    default = _DATATYPE_DEFAULT_.get(datatype)
                    prefix_limit_fields.update(
                        {
                            elem[0].replace(
                                "_prefix_limit", ""
                            ): napalm.base.helpers.convert(datatype, elem[1], default)
                        }
                    )
            bgp_config[bgp_group_name]["prefix_limit"] = build_prefix_limit(
                **prefix_limit_fields
            )
            if "multihop" in bgp_config[bgp_group_name].keys():
                # Delete 'multihop' key from the output
                del bgp_config[bgp_group_name]["multihop"]
                if bgp_config[bgp_group_name]["multihop_ttl"] == 0:
                    # Set ttl to default value 64
                    bgp_config[bgp_group_name]["multihop_ttl"] = 64

            bgp_config[bgp_group_name]["neighbors"] = {}
            for bgp_group_neighbor in bgp_group_peers.items():
                bgp_peer_address = napalm.base.helpers.ip(bgp_group_neighbor[0])
                if neighbor and bgp_peer_address != neighbor:
                    continue  # if filters applied, jump over all other neighbors
                bgp_group_details = bgp_group_neighbor[1]
                bgp_peer_details = {
                    field: _DATATYPE_DEFAULT_.get(datatype)
                    for field, datatype in _PEER_FIELDS_DATATYPE_MAP_.items()
                    if "_prefix_limit" not in field
                }
                for elem in bgp_group_details:
                    if not ("_prefix_limit" not in elem[0] and elem[1] is not None):
                        continue
                    datatype = _PEER_FIELDS_DATATYPE_MAP_.get(elem[0])
                    default = _DATATYPE_DEFAULT_.get(datatype)
                    key = elem[0]
                    value = elem[1]
                    if key in ["export_policy"]:
                        # next-hop self is applied on export IBGP sessions
                        bgp_peer_details["nhs"] = _check_nhs(value, nhs_policies)
                    if key in ["export_policy", "import_policy"]:
                        if isinstance(value, list):
                            value = " ".join(value)
                    if key == "local_address":
                        value = napalm.base.helpers.convert(
                            napalm.base.helpers.ip, value, value
                        )
                    bgp_peer_details.update(
                        {key: napalm.base.helpers.convert(datatype, value, default)}
                    )
                    bgp_peer_details["local_as"] = napalm.base.helpers.as_number(
                        bgp_peer_details["local_as"]
                    )
                    bgp_peer_details["remote_as"] = napalm.base.helpers.as_number(
                        bgp_peer_details["remote_as"]
                    )
                    if key == "cluster":
                        bgp_peer_details["route_reflector_client"] = True
                        # we do not want cluster in the output
                        del bgp_peer_details["cluster"]

                if "cluster" in bgp_config[bgp_group_name].keys():
                    bgp_peer_details["route_reflector_client"] = True
                prefix_limit_fields = {}
                for elem in bgp_group_details:
                    if "_prefix_limit" in elem[0] and elem[1] is not None:
                        datatype = _PEER_FIELDS_DATATYPE_MAP_.get(elem[0])
                        default = _DATATYPE_DEFAULT_.get(datatype)
                        prefix_limit_fields.update(
                            {
                                elem[0].replace(
                                    "_prefix_limit", ""
                                ): napalm.base.helpers.convert(
                                    datatype, elem[1], default
                                )
                            }
                        )
                bgp_peer_details["prefix_limit"] = build_prefix_limit(
                    **prefix_limit_fields
                )
                bgp_config[bgp_group_name]["neighbors"][
                    bgp_peer_address
                ] = bgp_peer_details
                if neighbor and bgp_peer_address == neighbor_ip:
                    break  # found the desired neighbor

            if "cluster" in bgp_config[bgp_group_name].keys():
                # we do not want cluster in the output
                del bgp_config[bgp_group_name]["cluster"]

        return bgp_config