Skip to content

Commit

Permalink
Merge pull request #154 from netsys-lab/development
Browse files Browse the repository at this point in the history
Large SCION topology example and beaconing policies
  • Loading branch information
wonkr authored Aug 26, 2023
2 parents 8688eab + 53140bd commit 094180a
Show file tree
Hide file tree
Showing 10 changed files with 630 additions and 11 deletions.
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

0 comments on commit 094180a

Please sign in to comment.