Skip to content
Draft
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
55 changes: 55 additions & 0 deletions examples/scion/S09-scion-ip-gateway/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# SCION IP Gateway

In this example we demonstrate how to set up SCION IP gateways between ASes.

first we have to import the ScionSIGService class from seedemu.services

```python
from seedemu.services import ScionSIGService
```

Then we create the SIG service

```python
sig = ScionSIGService()
```

Now we can cerate hosts in ASes and install the SIG service. For this we also have to generate a SIG configuration using the setSigConfig() function. in the ScionAutonomosSystem class.

```python
# SIG in AS-150
as150.createHost("sig0").joinNetwork('net0')

as150.setSigConfig(sig_name="sig0",node_name="sig0",other_ia=(1,153), local_net = "172.16.11.0/24", remote_net = "172.16.12.0/24")
config = as150.getSigConfig("sig0")

sig.install("sig150").setConfig("sig0",config)
emu.addBinding(Binding('sig150', filter=Filter(nodeName='sig0', asn=150)))
```
Note that sig_name, node_name, other_ia, local_net, remote_net always have to be set where as the other parameters only need to be set if there are several sigs on the same node

Now we can create a SIG client in another AS

```python
as153.createHost("sig").joinNetwork('net0')

as153.setSigConfig(sig_name="sig0",node_name="sig", other_ia=(1,150), local_net = "172.16.12.0/24", remote_net = "172.16.11.0/24")
as153.setSigConfig(sig_name="sig1",node_name="sig", other_ia=(1,151), local_net = "172.16.13.0/24", remote_net = "172.16.14.0/24", ctrl_port=30260, data_port=30261, probe_port=30857)

config_sig0 = as153.getSigConfig("sig0")
config_sig1 = as153.getSigConfig("sig1")


sig.install("sig153").setConfig(sig_name="sig0",config=config_sig0)
sig.install("sig153").setConfig(sig_name="sig1",config=config_sig1)

emu.addBinding(Binding('sig153', filter=Filter(nodeName='sig', asn=153)))
```

Here we also see an example of having to set the ports in the sig config if there are several sigs on the same node.

At the end we should not forget to add the sig layer to the emulator

```python
emu.addService(sig)
```
117 changes: 117 additions & 0 deletions examples/scion/S09-scion-ip-gateway/scion-ip-gateway.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/env python3

from seedemu.compiler import Docker, Graphviz
from seedemu.core import Emulator, Binding, Filter
from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion, Ospf
from seedemu.layers.Scion import LinkType as ScLinkType
from seedemu.services import ScionSIGService



# Initialize
emu = Emulator()
base = ScionBase()
routing = ScionRouting()
scion_isd = ScionIsd()
scion = Scion()
ospf = Ospf()
sig = ScionSIGService()

# SCION ISDs
base.createIsolationDomain(1)

# Internet Exchange
base.createInternetExchange(100)

# AS-150
as150 = base.createAutonomousSystem(150)
scion_isd.addIsdAs(1, 150, is_core=True)
as150.createNetwork('net0')
as150_cs = as150.createControlService('cs1').joinNetwork('net0')
as150_router = as150.createRouter('br0')
as150_router.joinNetwork('net0').joinNetwork('ix100')
as150_router.crossConnect(153, 'br0', '10.50.0.2/29')


# node with node_name has to exist before its possible to create sig config
as150.createHost("sig0").joinNetwork('net0')

as150.setSigConfig(sig_name="sig0",node_name="sig0",other_ia=(1,153), local_net = "172.16.11.0/24", remote_net = "172.16.12.0/24")
config = as150.getSigConfig("sig0")

sig.install("sig150").setConfig("sig0",config)
emu.addBinding(Binding('sig150', filter=Filter(nodeName='sig0', asn=150)))



# AS-151
as151 = base.createAutonomousSystem(151)
scion_isd.addIsdAs(1, 151, is_core=True)
as151.createNetwork('net0')
as151.createControlService('cs1').joinNetwork('net0')
as151_router = as151.createRouter('br0').joinNetwork('net0').joinNetwork('ix100')

as151.createHost("sig").joinNetwork('net0')

# there has to be a host with node name in AS
as151.setSigConfig(sig_name="sig0",node_name="sig", other_ia=(1,153), local_net = "172.16.14.0/24", remote_net = "172.16.13.0/24")

config = as151.getSigConfig("sig0")


sig.install("sig151").setConfig("sig0",config)
emu.addBinding(Binding('sig151', filter=Filter(nodeName='sig', asn=151)))

# AS-152
as152 = base.createAutonomousSystem(152)
scion_isd.addIsdAs(1, 152, is_core=True)
as152.createNetwork('net0')
as152.createControlService('cs1').joinNetwork('net0')
as152.createRouter('br0').joinNetwork('net0').joinNetwork('ix100')

# AS-153
as153 = base.createAutonomousSystem(153)
scion_isd.addIsdAs(1, 153, is_core=False)
scion_isd.setCertIssuer((1, 153), issuer=150)
as153.createNetwork('net0')
as153_cs = as153.createControlService('cs1').joinNetwork('net0')
as153_router = as153.createRouter('br0')
as153_router.joinNetwork('net0')
as153_router.crossConnect(150, 'br0', '10.50.0.3/29')

as153.createHost("sig").joinNetwork('net0')

as153.setSigConfig(sig_name="sig0",node_name="sig", other_ia=(1,150), local_net = "172.16.12.0/24", remote_net = "172.16.11.0/24")
as153.setSigConfig(sig_name="sig1",node_name="sig", other_ia=(1,151), local_net = "172.16.13.0/24", remote_net = "172.16.14.0/24", ctrl_port=30260, data_port=30261, probe_port=30857)

config_sig0 = as153.getSigConfig("sig0")
config_sig1 = as153.getSigConfig("sig1")


sig.install("sig153").setConfig(sig_name="sig0",config=config_sig0)
sig.install("sig153").setConfig(sig_name="sig1",config=config_sig1)

emu.addBinding(Binding('sig153', filter=Filter(nodeName='sig', asn=153)))




# Inter-AS routing
scion.addIxLink(100, (1, 150), (1, 151), ScLinkType.Core)
scion.addIxLink(100, (1, 151), (1, 152), ScLinkType.Core)
scion.addIxLink(100, (1, 152), (1, 150), ScLinkType.Core)
scion.addXcLink((1, 150), (1, 153), ScLinkType.Transit)

# Rendering
emu.addLayer(base)
emu.addLayer(routing)
emu.addLayer(scion_isd)
emu.addLayer(scion)
emu.addLayer(ospf)
emu.addLayer(sig)

emu.render()

# Compilation
emu.compile(Docker(internetMapEnabled=True), './seed-compiled', override=True)
emu.compile(Graphviz(), './seed-compiled/graphviz', override=True)
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ pycryptodome==3.21.0
python-dateutil==2.9.0.post0
PyYAML==6.0.2
referencing==0.36.2
requests==2.22.0
requests==2.32.3
rlp==2.0.1
rpds-py==0.23.1
six==1.17.0
toolz==1.0.0
typing_extensions==4.12.2
urllib3==1.25.11
urllib3==1.26.20
varint==1.0.2
web3==5.31.1
websocket-client==1.8.0
Expand Down
58 changes: 58 additions & 0 deletions seedemu/core/ScionAutonomousSystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class ScionAutonomousSystem(AutonomousSystem):
__beaconing_policy: Dict[str, Dict]
__note: str # optional free form parameter that contains interesting information about AS. This will be included in beacons if it is set
__generateStaticInfoConfig: bool
__sigs_config: Dict[str, Dict] # data structure to hold configuration for sig nodes

def __init__(self, asn: int, subnetTemplate: str = "10.{}.0.0/16"):
"""!
Expand All @@ -157,6 +158,7 @@ def __init__(self, asn: int, subnetTemplate: str = "10.{}.0.0/16"):
self.__beaconing_policy = {}
self.__note = None
self.__generateStaticInfoConfig = False
self.__sigs_config = {} # data structure to hold configuration for sig nodes

def scope(self)-> Scope:
return Scope(ScopeTier.AS, as_id=self.getAsn())
Expand Down Expand Up @@ -306,6 +308,17 @@ def getTopology(self, isd: int) -> Dict:
"interfaces": rnode.getScionInterfaces()
}

# SIGs
sigs = {}
for name in self.__sigs_config.keys():
hostName = self.__sigs_config[name]["node_name"]
node = self.getHost(hostName)
addr = node.getInterfaces()[0].getAddress()
sigs[name] = {
'ctrl_addr': f"{addr}:{self.__sigs_config[name]['ctrl_port']}",
'data_addr': f"{addr}:{self.__sigs_config[name]['data_port']}"
}

return {
'attributes': self.getAsAttributes(isd),
'isd_as': f'{IA(isd, self.getScionAsn())}',
Expand All @@ -314,6 +327,7 @@ def getTopology(self, isd: int) -> Dict:
'discovery_service': control_services,
'border_routers': border_routers,
'dispatched_ports': '31000-32767',
'sigs': sigs,
}

def createControlService(self, name: str) -> Node:
Expand Down Expand Up @@ -345,6 +359,50 @@ def getControlService(self, name: str) -> Node:
"""
return self.__control_services[name]

def _checkPorts(self, ctrl_port: int, data_port: int, probe_port: int, node_name: str) -> bool:
for sig_name in self.__sigs_config.keys():
if self.__sigs_config[sig_name]["node_name"] == node_name:
if self.__sigs_config[sig_name]["ctrl_port"] == ctrl_port or self.__sigs_config[sig_name]["data_port"] == data_port or self.__sigs_config[sig_name]["probe_port"] == probe_port:
return False
return True

def setSigConfig(self, sig_name: str, node_name: str, other_ia: IA, local_net: str, remote_net: str, ctrl_port: int = 30256, data_port: int = 30056, probe_port: int = 30856, debug_level: str = "debug") -> ScionAutonomousSystem:
"""!
@brief Set the configuration for a SIG.

@param sig_name Name of the SIG.
@param other_ia IA of the other AS.
"""

assert sig_name not in self.__sigs_config, 'SIG with name {} already has a configuration.'.format(sig_name)
assert node_name in self.getHosts(), 'Host with name {} does not exist.'.format(node_name)
assert self._checkPorts(ctrl_port, data_port, probe_port, node_name), 'Ports are already in use.'


self.__sigs_config[sig_name] = {
"local_net": local_net,
"remote_net": remote_net,
"ctrl_port": ctrl_port,
"data_port": data_port,
"probe_port": probe_port,
"other_ia": other_ia,
"debug_level": debug_level,
"node_name": node_name
}

return self


def getSigConfig(self, sig_name: str) -> Dict:
"""!
@brief Get the configuration for a SIG.

@param sig_name Name of the SIG.
@returns Configuration.
"""
assert sig_name in self.__sigs_config, 'SIG with name {} does not have a configuration.'.format(sig_name)
return self.__sigs_config[sig_name]

def setNote(self, note: str) -> ScionAutonomousSystem:
"""!
@brief Set a note for the AS.
Expand Down
4 changes: 2 additions & 2 deletions seedemu/layers/ScionRouting.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def supportedModes(cls) -> OptionMode:
return OptionMode.BUILD_TIME
@classmethod
def default(cls):
return SetupSpecification.LOCAL_BUILD(CheckoutSpecification())
return SetupSpecification.PACKAGES(CheckoutSpecification())


# -------------------------------------------------------------------
Expand Down Expand Up @@ -329,7 +329,7 @@ def configure_base(self, emulator: Emulator) -> List[Router]:

if type == 'rs' :
if not has_bgp:
raise RuntimeError('SCION has no concept of Route Servers.')
continue
else:
self._installBird(obj)
self._configure_rs(obj)
Expand Down
2 changes: 1 addition & 1 deletion seedemu/layers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
from .ScionRouting import ScionRouting
from .ScionIsd import ScionIsd
from .Scion import Scion, SetupSpecification, CheckoutSpecification
from .EtcHosts import EtcHosts
from .EtcHosts import EtcHosts
Loading