Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large SCION topology example and beaconing policies #154

Merged
merged 2 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/scion/S02-scion-bgp-mixed/scion-bgp-mixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
as150.createNetwork('net1')
as150.createNetwork('net2')
as150.createNetwork('net3')
as150.setBeaconingIntervals('5s', '5s', '5s')
as150.setBeaconPolicy('core_registration', {'Filter': {'AllowIsdLoop': False}})
as150.createControlService('cs1').joinNetwork('net0')
as150.createControlService('cs2').joinNetwork('net2')
as150_br0 = as150.createRouter('br0')
Expand Down
2 changes: 2 additions & 0 deletions examples/scion/S05-scion-internet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bgp/
scion/
62 changes: 62 additions & 0 deletions examples/scion/S05-scion-internet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
SCION Internet Topology
=======================
Two topology examples showing a possible transition from a BGP-based to a
SCION-based Internet.

BGP Topology
------------
A "flattened" Internet topology with Tier-1 ISPs providing transit and three
IXes providing shortcuts between the other ASes including access networks and a
large content provider.

![BGP Internet Topology](./images/bgp_topology.png)

Lines with arrowheads indicate paid transit connections, dashed lines are used
for settlement-free peering. The three IXes are not ASes themselves, the are
transparent on the network layer. All IX participants are connected to a route
server in each IX enabling full multilateral peering.

### Running the Topology

```bash
./bgp-internet.py
cd bgp
docker-compose build
docker-compose up -d
```

SCION Topology
--------------
A relatively large pure SCION Internet topology created by promoting IXPs in the
BGP topology to ASes and exposing the internal structure of BGP ASes by
partitioning them into many SCION ASes. The topology is roughly divided
in two large Internet regions that are represented by ISD 1 and ISD 2.
Additional ISDs exist for large multi-region ASes that can be expected to run
their own ISD. All ASes contain a single internal network and a single control
service and border router. The following graph gives an overview of the AS-level
topology:

![SCION Internet Topology](./images/scion_topology.png)

SCION core ASes have double outlines, the other ASes are non-core ASes. Thick
lines represent core links, links with arrowheads are transit links. There are
no peering links. The topology consists of Tier-1 ASes, IXPs, a large content
provider and access networks of different sizes.

### Running the Topology

```bash
./scion-internet.py
cd scion
docker-compose build
docker compose up -d # use docker compose v2 (no hyphen)
```

### Implementation Notes

- Everything is in ISD 1 until AS multi-homing is implemented.
- IX networks are used for internal links within IXPs and large ASes that
consists of many SCION ASes to limit the number of Docker networks that have
to be created.
- Cross-connections are mainly used for core and transit links between the large
ASes.
176 changes: 176 additions & 0 deletions examples/scion/S05-scion-internet/bgp-internet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#!/usr/bin/env python3

from ipaddress import IPv4Network
from seedemu.compiler import Docker
from seedemu.core import Emulator
from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion, Ebgp
from seedemu.layers import PeerRelationship as PeerRel
from seedemu.layers.Scion import LinkType as ScLinkType


def create_as(isd, asn, is_core=False, issuer=None):
as_ = base.createAutonomousSystem(asn)
scion_isd.addIsdAs(isd, asn, is_core)
if not is_core:
scion_isd.setCertIssuer((isd, asn), issuer)
as_.createNetwork('net0')
as_.createControlService('cs1').joinNetwork('net0')
br = as_.createRouter('br0')
br.joinNetwork('net0')
return as_, br


class CrossConnectNetAssigner:
def __init__(self):
self.subnet_iter = IPv4Network("10.3.0.0/16").subnets(new_prefix=29)
self.xc_nets = {}

def next_addr(self, net):
if net not in self.xc_nets:
hosts = next(self.subnet_iter).hosts()
next(hosts) # Skip first IP (reserved for Docker)
self.xc_nets[net] = hosts
return "{}/29".format(next(self.xc_nets[net]))

xc_nets = CrossConnectNetAssigner()


# Initialize
emu = Emulator()
base = ScionBase()
routing = ScionRouting()
scion_isd = ScionIsd()
scion = Scion()
ebgp = Ebgp()

# SCION ISDs
base.createIsolationDomain(1)

# IXes
base.createInternetExchange(10) # Large IXP (east)
base.createInternetExchange(11) # Large IXP (west)
base.createInternetExchange(12) # Small IXP

# ASes
_, br = create_as(1, 50, is_core=True) # Tier-1 ISP
br.crossConnect(60, 'br0', xc_nets.next_addr('50-60'))
br.crossConnect(70, 'br0', xc_nets.next_addr('50-70'))
br.crossConnect(150, 'br0', xc_nets.next_addr('50-150'))
br.crossConnect(151, 'br0', xc_nets.next_addr('50-151'))
br.crossConnect(180, 'br0', xc_nets.next_addr('50-180'))
br.crossConnect(200, 'br0', xc_nets.next_addr('50-200'))
_, br = create_as(1, 60, is_core=True) # Tier-1 ISP
br.crossConnect(50, 'br0', xc_nets.next_addr('50-60'))
br.crossConnect(70, 'br0', xc_nets.next_addr('60-70'))
br.crossConnect(152, 'br0', xc_nets.next_addr('60-152'))
br.crossConnect(180, 'br0', xc_nets.next_addr('60-180'))
_, br = create_as(1, 70, is_core=True) # Tier-1 ISP
br.crossConnect(50, 'br0', xc_nets.next_addr('50-70'))
br.crossConnect(60, 'br0', xc_nets.next_addr('60-70'))
br.crossConnect(160, 'br0', xc_nets.next_addr('70-160'))
br.crossConnect(161, 'br0', xc_nets.next_addr('70-161'))
br.crossConnect(162, 'br0', xc_nets.next_addr('70-162'))
br.crossConnect(163, 'br0', xc_nets.next_addr('70-163'))
br.crossConnect(170, 'br0', xc_nets.next_addr('70-170'))
br.crossConnect(200, 'br0', xc_nets.next_addr('70-200'))
_, br = create_as(1, 170, issuer=70) # Access Network
br.joinNetwork('ix11').joinNetwork('ix12')
br.crossConnect(70, 'br0', xc_nets.next_addr('70-170'))
_, br = create_as(1, 180, issuer=50) # Large Access Network
br.joinNetwork('ix10')
br.crossConnect(50, 'br0', xc_nets.next_addr('50-180'))
br.crossConnect(60, 'br0', xc_nets.next_addr('60-180'))
_, br = create_as(1, 200, issuer=50) # Content Provider
br.joinNetwork('ix10').joinNetwork('ix11').joinNetwork('ix12')
br.crossConnect(50, 'br0', xc_nets.next_addr('50-200'))
br.crossConnect(70, 'br0', xc_nets.next_addr('70-200'))
br.crossConnect(150, 'br0', xc_nets.next_addr('150-200'))
br.crossConnect(163, 'br0', xc_nets.next_addr('163-200'))
_, br = create_as(1, 150, issuer=50)
br.joinNetwork('ix10')
br.crossConnect(50, 'br0', xc_nets.next_addr('50-150'))
br.crossConnect(200, 'br0', xc_nets.next_addr('150-200'))
_, br = create_as(1, 151, issuer=50)
br.joinNetwork('ix10')
br.crossConnect(50, 'br0', xc_nets.next_addr('50-151'))
_, br = create_as(1, 152, issuer=60)
br.joinNetwork('ix10')
br.crossConnect(60, 'br0', xc_nets.next_addr('60-152'))
_, br = create_as(1, 160, issuer=70)
br.joinNetwork('ix11').joinNetwork('ix12')
br.crossConnect(70, 'br0', xc_nets.next_addr('70-160'))
_, br = create_as(1, 161, issuer=70)
br.joinNetwork('ix12')
br.crossConnect(70, 'br0', xc_nets.next_addr('70-161'))
_, br = create_as(1, 162, issuer=70)
br.joinNetwork('ix12')
br.crossConnect(70, 'br0', xc_nets.next_addr('70-162'))
_, br = create_as(1, 163, issuer=70)
br.joinNetwork('ix11').joinNetwork('ix12')
br.crossConnect(70, 'br0', xc_nets.next_addr('70-163'))
br.crossConnect(200, 'br0', xc_nets.next_addr('163-200'))

# BGP
ebgp.addCrossConnectPeering(70, 50, PeerRel.Peer)
ebgp.addCrossConnectPeering(50, 60, PeerRel.Peer)
ebgp.addCrossConnectPeering(60, 70, PeerRel.Peer)
ebgp.addCrossConnectPeering(70, 170, PeerRel.Provider)
ebgp.addCrossConnectPeering(70, 160, PeerRel.Provider)
ebgp.addCrossConnectPeering(70, 161, PeerRel.Provider)
ebgp.addCrossConnectPeering(70, 162, PeerRel.Provider)
ebgp.addCrossConnectPeering(70, 163, PeerRel.Provider)
ebgp.addCrossConnectPeering(70, 200, PeerRel.Provider)
ebgp.addCrossConnectPeering(50, 200, PeerRel.Provider)
ebgp.addCrossConnectPeering(50, 150, PeerRel.Provider)
ebgp.addCrossConnectPeering(50, 151, PeerRel.Provider)
ebgp.addCrossConnectPeering(50, 180, PeerRel.Provider)
ebgp.addCrossConnectPeering(60, 180, PeerRel.Provider)
ebgp.addCrossConnectPeering(60, 152, PeerRel.Provider)
ebgp.addCrossConnectPeering(200, 163, PeerRel.Peer)
ebgp.addCrossConnectPeering(200, 150, PeerRel.Peer)
peers_ix12 = [160, 161, 162, 163, 170, 200]
for peer in peers_ix12:
ebgp.addRsPeer(12, peer)
peers_ix11 = [160, 163, 170, 200]
for peer in peers_ix11:
ebgp.addRsPeer(11, peer)
peers_ix10 = [150, 151, 152, 180, 200]
for peer in peers_ix10:
ebgp.addRsPeer(10, peer)

# SCION links
scion.addXcLink((1, 70), (1, 50), ScLinkType.Core)
scion.addXcLink((1, 50), (1, 60), ScLinkType.Core)
scion.addXcLink((1, 60), (1, 70), ScLinkType.Core)
scion.addXcLink((1, 70), (1, 170), ScLinkType.Transit)
scion.addXcLink((1, 70), (1, 160), ScLinkType.Transit)
scion.addXcLink((1, 70), (1, 161), ScLinkType.Transit)
scion.addXcLink((1, 70), (1, 162), ScLinkType.Transit)
scion.addXcLink((1, 70), (1, 163), ScLinkType.Transit)
scion.addXcLink((1, 70), (1, 200), ScLinkType.Transit)
scion.addXcLink((1, 50), (1, 200), ScLinkType.Transit)
scion.addXcLink((1, 50), (1, 150), ScLinkType.Transit)
scion.addXcLink((1, 50), (1, 151), ScLinkType.Transit)
scion.addXcLink((1, 50), (1, 180), ScLinkType.Transit)
scion.addXcLink((1, 60), (1, 180), ScLinkType.Transit)
scion.addXcLink((1, 60), (1, 152), ScLinkType.Transit)
scion.addXcLink((1, 200), (1, 163), ScLinkType.Peer)
scion.addXcLink((1, 200), (1, 150), ScLinkType.Peer)
for a, b in [(a, b) for a in peers_ix12 for b in peers_ix12 if a < b]:
scion.addIxLink(12, (1, a), (1, b), ScLinkType.Peer)
for a, b in [(a, b) for a in peers_ix11 for b in peers_ix11 if a < b]:
scion.addIxLink(11, (1, a), (1, b), ScLinkType.Peer)
for a, b in [(a, b) for a in peers_ix10 for b in peers_ix10 if a < b]:
scion.addIxLink(10, (1, a), (1, b), ScLinkType.Peer)

# Rendering
emu.addLayer(base)
emu.addLayer(routing)
emu.addLayer(scion_isd)
emu.addLayer(scion)
emu.addLayer(ebgp)

emu.render()

# Compilation
emu.compile(Docker(), './bgp')
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading