Skip to content

Commit

Permalink
Improve missing_sessions Jinja2 filters
Browse files Browse the repository at this point in the history
It should now work correctly with PeeringDB network objects by returning
all possible sessions. It does not exclude the existing ones (for now).
  • Loading branch information
gmazoyer committed May 17, 2024
1 parent b12e5fb commit f7d9b78
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 25 deletions.
4 changes: 4 additions & 0 deletions docs/templating/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ On an autonomous system, it will return all sessions that can be configured
between two autonomous systems. You must provide a second AS, providing an IXP
is optional.

When one of the parameters is a PeeringDB network object, e.g. when used to
send an e-mail to an AS unknown to Peering Manager, all possible sessions will
be returned (according to PeeringDB).

Example:

```no-highlight
Expand Down
31 changes: 23 additions & 8 deletions peering_manager/jinja2/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
Router,
)
from peering_manager.models.features import ConfigContextMixin, TagsMixin
from peeringdb.functions import get_shared_facilities
from peeringdb.functions import get_possible_peering_sessions, get_shared_facilities
from peeringdb.models import Network
from utils.functions import get_key_in_hash, serialize_object

Expand Down Expand Up @@ -637,17 +637,32 @@ def shared_facilities(value, other):
def missing_sessions(value, other, ixp=None):
"""
Returns all missing sessions between two ASNs, optionally on an IXP.
When used with a PeeringDB network record, this will return possible
sessions between the two networks without excluding already existing
sessions (known limitation).
"""
# Comparing two autonomous systems
if isinstance(value, AutonomousSystem) and isinstance(other, AutonomousSystem):
return value.get_missing_peering_sessions(other, internet_exchange_point=ixp)

ixlan = ixp.peeringdb_ixlan if ixp is not None else None

if isinstance(value, AutonomousSystem):
as1 = value
as2 = other
elif isinstance(other, AutonomousSystem):
as1 = other
as2 = value
network_a = value.peeringdb_network
elif isinstance(value, Network):
network_a = value
else:
raise ValueError(f"{value} is not an autonomous system or a peeringdb network")

if isinstance(other, AutonomousSystem):
network_b = other.peeringdb_network
elif isinstance(other, Network):
network_b = other
else:
raise ValueError(f"at least {value} or {other} must be an autonomous system")
raise ValueError(f"{other} is not an autonomous system or a peeringdb network")

return as1.get_missing_peering_sessions(as2, internet_exchange_point=ixp)
return get_possible_peering_sessions(network_a, network_b, ixlan=ixlan)


def prefix_list(value, family=0):
Expand Down
42 changes: 25 additions & 17 deletions peeringdb/functions.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from .models import Facility, IXLan, IXLanPrefix, NetworkFacility, NetworkIXLan
from .models import Facility, IXLan, NetworkFacility, NetworkIXLan

__all__ = (
"get_possible_peering_sessions",
"get_shared_internet_exchanges",
"get_shared_facilities",
"get_ixlan_prefixes",
)


Expand All @@ -12,21 +12,38 @@ def get_shared_internet_exchanges(as1, as2):
Returns shared IXPs (via PeeringDB IXLAN objects) between two autonomous systems
based on PeeringDB data.
"""
# If both AS are the same or one of each has not PeeringDB record
# If both AS are the same or one of each has no PeeringDB record
# Cannot find shared IXPs
if as1 == as2 or as1 is None or as2 is None:
if as1 is None or as2 is None or as1 == as2:
return IXLan.objects.none()

# Find IX LANs to which AS are participating to and get IDs
ixlan_ids_1 = NetworkIXLan.objects.filter(net=as1).values_list("ixlan", flat=True)
ixlan_ids_2 = NetworkIXLan.objects.filter(net=as2).values_list("ixlan", flat=True)

# Return IXP LANs found previously
return IXLan.objects.filter(pk__in=ixlan_ids_1).intersection(
IXLan.objects.filter(pk__in=ixlan_ids_2)
return IXLan.objects.filter(pk__in=ixlan_ids_1) & IXLan.objects.filter(
pk__in=ixlan_ids_2
)


def get_possible_peering_sessions(as1, as2, ixlan=None):
# If both AS are the same or one of each has no PeeringDB record
# Cannot find sessions for AS1 to peer with AS2
if as1 is None or as2 is None or as1 == as2:
return NetworkIXLan.objects.none()

# Find network IX LANs of AS2 that could be used to peer with AS1
if ixlan:
ixlan_ids = NetworkIXLan.objects.filter(net=as1, ixlan=ixlan).values_list(
"ixlan", flat=True
)
else:
ixlan_ids = NetworkIXLan.objects.filter(net=as1).values_list("ixlan", flat=True)

return NetworkIXLan.objects.filter(net=as2, ixlan__in=ixlan_ids)


def get_shared_facilities(as1, as2):
"""
Returns shared facilities between two autonomous systems based on PeeringDB data.
Expand All @@ -40,15 +57,6 @@ def get_shared_facilities(as1, as2):
netfac_ids_1 = NetworkFacility.objects.filter(net=as1).values_list("fac", flat=True)
netfac_ids_2 = NetworkFacility.objects.filter(net=as2).values_list("fac", flat=True)

return Facility.objects.filter(pk__in=netfac_ids_1).intersection(
Facility.objects.filter(pk__in=netfac_ids_2)
return Facility.objects.filter(pk__in=netfac_ids_1) & Facility.objects.filter(
pk__in=netfac_ids_2
)


def get_ixlan_prefixes(ixlan):
"""
Returns all prefixes used on an IXP LAN.
"""
if not ixlan or not isinstance(ixlan, IXLan):
return IXLanPrefix.objects.none()
return IXLanPrefix.objects.filter(ixlan=ixlan)

0 comments on commit f7d9b78

Please sign in to comment.