From 02eb6bef8019d8bfc62bbf397ab31c6807b6353f Mon Sep 17 00:00:00 2001 From: Lorin Urbantat Date: Mon, 18 Mar 2024 10:16:24 +0000 Subject: [PATCH 01/46] first steps seed file generation for topology (command line argument, isd code generation, start as code generation) --- tools/topogen.py | 2 + tools/topology/config.py | 11 ++++ tools/topology/seed.py | 121 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tools/topology/seed.py diff --git a/tools/topogen.py b/tools/topogen.py index eb57e9e8ab..8f193160e6 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -49,6 +49,8 @@ def add_arguments(parser): to be built manually e.g. when running acceptance tests)') parser.add_argument('--features', help='Feature flags to enable, a comma separated list\ e.g. foo,bar enables foo and bar feature.') + parser.add_argument('-s','--seed',action='store_true',help='Generate a seed file for the topology') + return parser diff --git a/tools/topology/config.py b/tools/topology/config.py index aa70bfbb2e..a1e5b9fb1c 100644 --- a/tools/topology/config.py +++ b/tools/topology/config.py @@ -37,6 +37,7 @@ from topology.cert import CertGenArgs, CertGenerator from topology.common import ArgsBase from topology.docker import DockerGenArgs, DockerGenerator +from topology.seed import SeedGenArgs, SeedGenerator from topology.go import GoGenArgs, GoGenerator from topology.net import ( NetworkDescription, @@ -108,6 +109,8 @@ def _ensure_uniq_ases(self): def _generate_with_topo(self, topo_dicts): self._generate_go(topo_dicts) + if self.args.seed: + self._generate_seed(topo_dicts) if self.args.docker: self._generate_docker(topo_dicts) else: @@ -157,6 +160,14 @@ def _generate_docker(self, topo_dicts): def _docker_args(self, topo_dicts): return DockerGenArgs(self.args, topo_dicts, self.all_networks) + def _generate_seed(self, topo_dicts): + args = self._seed_args(topo_dicts) + seed_gen = SeedGenerator(args) + seed_gen.generate() + + def _seed_args(self, topo_dicts): + return SeedGenArgs(self.args, topo_dicts, self.all_networks) + def _generate_monitoring_conf(self, topo_dicts): args = self._monitoring_args(topo_dicts) mon_gen = MonitoringGenerator(args) diff --git a/tools/topology/seed.py b/tools/topology/seed.py new file mode 100644 index 0000000000..5ffacc3e23 --- /dev/null +++ b/tools/topology/seed.py @@ -0,0 +1,121 @@ +x# Copyright 2024 ETH Zürich, Lorin Urbantat +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Mapping +import os + +from topology.util import write_file +from topology.common import ( + ArgsTopoDicts +) +from topology.net import NetworkDescription, IPNetwork + + +SEED_CONF = "scion-seed.py" + + +class SeedGenArgs(ArgsTopoDicts): + def __init__(self, args, topo_dicts, + networks: Mapping[IPNetwork, NetworkDescription]): + """ + :param object args: Contains the passed command line arguments as named attributes. + :param dict topo_dicts: The generated topo dicts from TopoGenerator. + :param dict networks: The generated network descriptions from NetworkGenerator. + """ + super().__init__(args, topo_dicts) + self.networks = networks + +class SeedGenerator(object): + def __init__(self, args): + """ + :param SeedGenArgs args: Contains the passed command line arguments and topo dicts. + """ + self.args = args + self.out_file = """ +#!/usr/bin/env python3 + +from seedemu.compiler import Docker +from seedemu.core import Emulator +from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion +from seedemu.layers.Scion import LinkType as ScLinkType + +# Initialize +emu = Emulator() +base = ScionBase() +routing = ScionRouting()t +scion_isd = ScionIsd() +scion = Scion() + +""" + + def generate(self): + + self.out_file += self._create_ISD() + + self.out_file += self._create_AS() + + self.out_file += """ +# Rendering +emu.addLayer(base) +emu.addLayer(routing) +emu.addLayer(scion_isd) +emu.addLayer(scion) + +emu.render() + +# Compilation +emu.compile(Docker(), './output') +""" + + write_file(os.path.join(self.args.output_dir, SEED_CONF), self.out_file) + + def _isd_Set(self): + isds = set() + for As in self.args.topo_dicts: + # get Id of every ISD + isd = As.ISD()[3] + isds.add(isd) + return isds + + + def _create_ISD(self): + code = "# Create ISDs\n" + # get set of ISDs + isds = self._isd_Set() + # write code for each ISD + for isd in isds: + code += f"base.createIsolationDomain({isd})\n" + + code += "\n\n" + return code + + def _create_AS(self): + code = "# Ases \n" + for As in self.args.topo_dicts: + as_num = As.AS().split(':')[2] + isd_num = As.ISD()[3] + is_core = True if (self.args.topo_dicts[As]["attributes"] and self.args.topo_dicts[As]["attributes"][0] == 'core') else False + print(is_core) + code += f""" +# AS-{as_num} +as{as_num} = base.createAutonomousSystem({as_num}) +scion_isd().addIsdAs({isd_num},{as_num},is_core={is_core}) +""" + + return code + + def _create_links(self): + pass # TODO: implement _create_links function + + From 992475abbd8b43a2adcb0eed095a309ad56b0f71 Mon Sep 17 00:00:00 2001 From: Lorin Urbantat Date: Mon, 18 Mar 2024 13:02:17 +0000 Subject: [PATCH 02/46] added cert_issuer to topo_dict --- tools/topology/topo.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/topology/topo.py b/tools/topology/topo.py index 298605bdc8..ba37c5965b 100644 --- a/tools/topology/topo.py +++ b/tools/topology/topo.py @@ -238,8 +238,10 @@ def _generate_as_topo(self, topo_id, as_conf): for attr in ['core']: if as_conf.get(attr, False): attributes.append(attr) + cert_issuer = as_conf.get('cert_issuer', None) self.topo_dicts[topo_id] = { 'attributes': attributes, + 'cert_issuer': cert_issuer, 'isd_as': str(topo_id), 'mtu': mtu, } From 0d8d50f8cca204174fe5950cf2adc61e1138407e Mon Sep 17 00:00:00 2001 From: Lorin Urbantat Date: Mon, 18 Mar 2024 13:02:31 +0000 Subject: [PATCH 03/46] added cert_issuer setting --- tools/topology/seed.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 5ffacc3e23..e8b3c48449 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -1,4 +1,4 @@ -x# Copyright 2024 ETH Zürich, Lorin Urbantat +# Copyright 2024 ETH Zürich, Lorin Urbantat # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -106,13 +106,17 @@ def _create_AS(self): as_num = As.AS().split(':')[2] isd_num = As.ISD()[3] is_core = True if (self.args.topo_dicts[As]["attributes"] and self.args.topo_dicts[As]["attributes"][0] == 'core') else False - print(is_core) code += f""" # AS-{as_num} as{as_num} = base.createAutonomousSystem({as_num}) scion_isd().addIsdAs({isd_num},{as_num},is_core={is_core}) -""" +""" + if not is_core: + issuer_isd_num = self.args.topo_dicts[As]["cert_issuer"].split(':')[-1] + code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={issuer_isd_num})" + + code += "\n\n" return code def _create_links(self): From 225c903b8fac6f2fbde49def0c68b19a6f438911 Mon Sep 17 00:00:00 2001 From: Lorin Urbantat Date: Mon, 18 Mar 2024 14:57:57 +0000 Subject: [PATCH 04/46] added, control service generation --- tools/topology/seed.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index e8b3c48449..5882a6ad96 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -53,7 +53,7 @@ def __init__(self, args): # Initialize emu = Emulator() base = ScionBase() -routing = ScionRouting()t +routing = ScionRouting() scion_isd = ScionIsd() scion = Scion() @@ -100,21 +100,32 @@ def _create_ISD(self): code += "\n\n" return code + + + def _create_AS(self): code = "# Ases \n" for As in self.args.topo_dicts: + as_num = As.AS().split(':')[2] isd_num = As.ISD()[3] is_core = True if (self.args.topo_dicts[As]["attributes"] and self.args.topo_dicts[As]["attributes"][0] == 'core') else False + # create basic As config code += f""" # AS-{as_num} as{as_num} = base.createAutonomousSystem({as_num}) scion_isd().addIsdAs({isd_num},{as_num},is_core={is_core}) -""" +""" + # set cert Issuer if not core AS if not is_core: issuer_isd_num = self.args.topo_dicts[As]["cert_issuer"].split(':')[-1] - code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={issuer_isd_num})" + code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={issuer_isd_num})\n" + # create internal network + code += f"as{as_num}.createNetwork('net0')\n" + # create control Service + code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" + # create border router code += "\n\n" return code From 166795a470ea82958a3e9e09c452d5daf3b4484b Mon Sep 17 00:00:00 2001 From: Lorin Urbantat Date: Wed, 20 Mar 2024 15:58:25 +0000 Subject: [PATCH 05/46] add border router generation --- tools/topology/seed.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 5882a6ad96..48a8309af7 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -75,7 +75,7 @@ def generate(self): emu.render() # Compilation -emu.compile(Docker(), './output') +emu.compile(Docker(internetMapEnabled=True), './output') """ write_file(os.path.join(self.args.output_dir, SEED_CONF), self.out_file) @@ -114,7 +114,7 @@ def _create_AS(self): code += f""" # AS-{as_num} as{as_num} = base.createAutonomousSystem({as_num}) -scion_isd().addIsdAs({isd_num},{as_num},is_core={is_core}) +scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core}) """ # set cert Issuer if not core AS if not is_core: @@ -125,8 +125,12 @@ def _create_AS(self): code += f"as{as_num}.createNetwork('net0')\n" # create control Service code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" - # create border router - + # create routers + border_routers = self.args.topo_dicts[As]["border_routers"] + for router in border_routers: + br_name = "br" + router.split('-')[2] + code += f"as_{as_num}_{br_name}.createRouter('{br_name}').joinNetwork('net0')\n" + code += "\n\n" return code From a33e29751400b705a1507a4b97b5855bbac8006c Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 25 Mar 2024 09:35:56 +0100 Subject: [PATCH 06/46] first draft of seed from topo working --- tools/topology/seed.py | 89 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 48a8309af7..bfdf3c6c4d 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -14,6 +14,8 @@ from typing import Mapping import os +import subprocess +from ipaddress import IPv4Network from topology.util import write_file from topology.common import ( @@ -36,6 +38,19 @@ def __init__(self, args, topo_dicts, super().__init__(args, topo_dicts) self.networks = networks +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])) + + class SeedGenerator(object): def __init__(self, args): """ @@ -65,7 +80,8 @@ def generate(self): self.out_file += self._create_AS() - self.out_file += """ + + self.out_file += f""" # Rendering emu.addLayer(base) emu.addLayer(routing) @@ -75,10 +91,13 @@ def generate(self): emu.render() # Compilation -emu.compile(Docker(internetMapEnabled=True), './output') +emu.compile(Docker(internetMapEnabled=True), './{self.args.output_dir}/seed-compiled') """ - + # write seed file write_file(os.path.join(self.args.output_dir, SEED_CONF), self.out_file) + # generate simulation from seed file + print("\n\nRunning Seed Generation\n\n") + subprocess.run(["python", self.args.output_dir + "/" + SEED_CONF]) def _isd_Set(self): isds = set() @@ -104,9 +123,15 @@ def _create_ISD(self): def _create_AS(self): + + xc_nets = CrossConnectNetAssigner() + + # keep track of links + links = [] + code = "# Ases \n" - for As in self.args.topo_dicts: + for As in self.args.topo_dicts: as_num = As.AS().split(':')[2] isd_num = As.ISD()[3] is_core = True if (self.args.topo_dicts[As]["attributes"] and self.args.topo_dicts[As]["attributes"][0] == 'core') else False @@ -127,14 +152,60 @@ def _create_AS(self): code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" # create routers border_routers = self.args.topo_dicts[As]["border_routers"] + for router in border_routers: br_name = "br" + router.split('-')[2] - code += f"as_{as_num}_{br_name}.createRouter('{br_name}').joinNetwork('net0')\n" - + code += f"as_{as_num}_{br_name} = as{as_num}.createRouter('{br_name}').joinNetwork('net0')\n" + # create cross connect + interfaces = border_routers[router]['interfaces'] + for interface in interfaces: + peer_as = interfaces[interface]['isd_as'].split(':')[2] + link_type = interfaces[interface]['link_to'] + remote_addr = interfaces[interface]['underlay']['remote'] + # find other AS bridge name + other_br_name = self.__other_bridge_name(remote_addr) + # generate new address because addresses form Topo-Tool dont work with seed + # always order as_nums to have unique name for both sides + if (as_num < peer_as): + addr = xc_nets.next_addr(f"{as_num}_{peer_as}") + else : + addr = xc_nets.next_addr(f"{peer_as}_{as_num}") + # generate code + code += f"as_{as_num}_{br_name}.crossConnect({peer_as},'{other_br_name}','{addr}')\n" + if ((isd_num,peer_as,as_num,link_type) not in links and link_type != "parent"): + links.append((isd_num,as_num,peer_as,link_type)) + code += "\n\n" - return code - def _create_links(self): - pass # TODO: implement _create_links function + # create inter-AS links + code += "# Inter-AS routing\n" + code += self.__inter_AS_links(links) + code += "\n\n" + return code + def __other_bridge_name(self,address): + for As in self.args.topo_dicts: + as_num = As.AS().split(':')[2] + border_routers = self.args.topo_dicts[As]["border_routers"] + for router in border_routers: + br_name = "br" + router.split('-')[2] + interfaces = border_routers[router]['interfaces'] + for interface in interfaces: + addr = interfaces[interface]['underlay']['public'] + if address == addr: + return f"br{router.split('-')[2]}" + return None + + def __inter_AS_links(self, links): + code = "" + # find link pairs + for link in links: + isd1 = link[0] + as1 = link[1] + as2 = link[2] + link_type = link[3] + if link_type == "child": + link_type = "Transit" + code += f"scion.addXcLink(({isd1}, {as1}), ({isd1}, {as2}), ScLinkType.{link_type})\n" + return code \ No newline at end of file From 1cd81f3f9fb68a34d2a0a6fb0b566a83a0f711f9 Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 1 Apr 2024 14:25:37 +0200 Subject: [PATCH 07/46] first draft of seed from topo working --- tools/topology/seed.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index bfdf3c6c4d..4aae838f65 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -205,7 +205,12 @@ def __inter_AS_links(self, links): as1 = link[1] as2 = link[2] link_type = link[3] + # convert link types to seed format if link_type == "child": link_type = "Transit" + elif link_type == "core": + link_type = "Core" + elif link_type == "peer": + link_type = "Peer" code += f"scion.addXcLink(({isd1}, {as1}), ({isd1}, {as2}), ScLinkType.{link_type})\n" return code \ No newline at end of file From 4b837b41984b0b8ae20fc83848770e541ed2af07 Mon Sep 17 00:00:00 2001 From: bruol Date: Tue, 2 Apr 2024 11:10:04 +0200 Subject: [PATCH 08/46] added ipv6 check --- tools/topology/seed.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 4aae838f65..bf1d93df39 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -38,6 +38,8 @@ def __init__(self, args, topo_dicts, super().__init__(args, topo_dicts) self.networks = networks + +# copyright @lschulz -- https://github.com/Bruol/seed-emulator/blob/master/examples/scion/S05-scion-internet/scion-internet.py class CrossConnectNetAssigner: def __init__(self): self.subnet_iter = IPv4Network("10.3.0.0/16").subnets(new_prefix=29) @@ -76,6 +78,9 @@ def __init__(self, args): def generate(self): + # Seed does not support IPv6 thus throw error if IPv6 is used + self.check_IPv6() + self.out_file += self._create_ISD() self.out_file += self._create_AS() @@ -120,8 +125,11 @@ def _create_ISD(self): return code - - + def check_IPv6(self): + for network in self.args.networks: + if network._version == 6: + raise Exception("Seed does not support IPv6. Please use IPv4 only.") + def _create_AS(self): xc_nets = CrossConnectNetAssigner() From a00c759f5522f34cb8a8cbd219a7614e0d9fb17f Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 3 Apr 2024 17:59:16 +0200 Subject: [PATCH 09/46] completely redid seed file generation. its now based on parsing the yaml file instead of using the given data structure --- tools/topology/seed.py | 452 +++++++++++++++++++++++++++++++---------- 1 file changed, 350 insertions(+), 102 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index bf1d93df39..20537818c2 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -22,11 +22,11 @@ ArgsTopoDicts ) from topology.net import NetworkDescription, IPNetwork - +import yaml SEED_CONF = "scion-seed.py" - +# class to manage seed arguments class SeedGenArgs(ArgsTopoDicts): def __init__(self, args, topo_dicts, networks: Mapping[IPNetwork, NetworkDescription]): @@ -40,6 +40,7 @@ def __init__(self, args, topo_dicts, # copyright @lschulz -- https://github.com/Bruol/seed-emulator/blob/master/examples/scion/S05-scion-internet/scion-internet.py +# class to generate IP addresses for cross connect links class CrossConnectNetAssigner: def __init__(self): self.subnet_iter = IPv4Network("10.3.0.0/16").subnets(new_prefix=29) @@ -52,15 +53,51 @@ def next_addr(self, net): self.xc_nets[net] = hosts return "{}/29".format(next(self.xc_nets[net])) - class SeedGenerator(object): + # define class variables + _topo_file : dict + _args : SeedGenArgs + _out_file : str + _links : list + _br : dict + _internetMapEnabled : bool=True + _SeedCompiler : str="Docker" + _skipIPv6Check : bool=False + def __init__(self, args): """ :param SeedGenArgs args: Contains the passed command line arguments and topo dicts. + + Generates a seed file for the SCION topology. """ - self.args = args - self.out_file = """ -#!/usr/bin/env python3 + self._args = args + + self._parseFeatures() + + with open(args.topo_config,"r") as f: + self._topo_file = yaml.load(f, Loader=yaml.SafeLoader) + + def _parseFeatures(self): + if "SeedInternetMapDisable" in self._args.features: + self._internetMapEnabled = False + if "SeedCompilerGraphviz" in self._args.features: + self._SeedCompiler = "Graphviz" + if "SeedSkipIPv6Check" in self._args.features: + self._skipIPv6Check = True + + + + def generate(self): + """ + generate function called by ./config.py to generate seed file + """ + + # Seed does not support IPv6 thus throw error if IPv6 is used + if not self._skipIPv6Check: + self._check_IPv6() + + # write header of seed file + self._out_file = """ from seedemu.compiler import Docker from seedemu.core import Emulator @@ -76,17 +113,20 @@ def __init__(self, args): """ - def generate(self): - - # Seed does not support IPv6 thus throw error if IPv6 is used - self.check_IPv6() + # build appropriate link data structure + self._links = self._parse_links() + + self._parse_borderRouter_interfaces() - self.out_file += self._create_ISD() + self._generate_addresses() + + self._out_file += self._create_ISD() - self.out_file += self._create_AS() + self._out_file += self._create_AS() + self._out_file += self._create_Routing() - self.out_file += f""" + self._out_file += f""" # Rendering emu.addLayer(base) emu.addLayer(routing) @@ -96,24 +136,29 @@ def generate(self): emu.render() # Compilation -emu.compile(Docker(internetMapEnabled=True), './{self.args.output_dir}/seed-compiled') +emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}), './{self._args.output_dir}/seed-compiled') """ # write seed file - write_file(os.path.join(self.args.output_dir, SEED_CONF), self.out_file) + write_file(os.path.join(self._args.output_dir, SEED_CONF), self._out_file) # generate simulation from seed file print("\n\nRunning Seed Generation\n\n") - subprocess.run(["python", self.args.output_dir + "/" + SEED_CONF]) + subprocess.run(["python", self._args.output_dir + "/" + SEED_CONF]) def _isd_Set(self): + """ + Generate a set of ISDs from the topo file + """ isds = set() - for As in self.args.topo_dicts: + for As in self._topo_file["ASes"]: # get Id of every ISD - isd = As.ISD()[3] + isd = As.split('-')[0] isds.add(isd) return isds - def _create_ISD(self): + """ + Generate code for creating ISDs + """ code = "# Create ISDs\n" # get set of ISDs isds = self._isd_Set() @@ -124,13 +169,226 @@ def _create_ISD(self): code += "\n\n" return code - - def check_IPv6(self): - for network in self.args.networks: + def _check_IPv6(self): + """ + Check if any network is IPv6 + """ + for network in self._args.networks: if network._version == 6: - raise Exception("Seed does not support IPv6. Please use IPv4 only.") - + raise Exception("Seed does not support IPv6. Please use IPv4 only. If you want to try anyway use the feature flag SeedSkipIPv6Check.") + + def _parse_AS_properties(self, As): + """ + Read AS properties from topo file + """ + as_num = As.split(':')[2] + isd_num = As.split('-')[0] + + # handle optional properties + as_dict = self._topo_file["ASes"][As] + + is_core = as_dict['core'] if 'core' in as_dict else False + cert_issuer = as_dict['cert_issuer'].split(':')[2] if 'cert_issuer' in as_dict else None + as_int_bw = as_dict['bandwidth'] if 'bandwidth' in as_dict else 0 + as_int_lat = as_dict['latency'] if 'latency' in as_dict else 0 + as_int_drop = as_dict['drop'] if 'drop' in as_dict else 0 + as_int_mtu = as_dict['mtu'] if 'mtu' in as_dict else None + + return as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu + + def _read_link_properties(self, link): + """ + Read link properties from topo file + """ + a = link['a'] + b = link['b'] + link_type = self._convert_link_type(link['linkAtoB']) + # read optional properties + if "mtu" in link: + mtu = link['mtu'] + else: + mtu = None + + if "bandwidth" in link: + bandwidth = link['bandwidth'] + else: + bandwidth = 0 # seed ignores value 0 + + if "latency" in link: + latency = link['latency'] + else: + latency = 0 # seed ignores value 0 + + if "drop" in link: + drop = link['drop'] + else: + drop = 0 # seed ignores value 0 + + return a, b, link_type, mtu, bandwidth, latency, drop + + def _convert_link_type(self, link_type): + """ + Convert link type from topo file to seed format + """ + if link_type == "CHILD": + return "ScLinkType.Transit" + elif link_type == "PEER": + return "ScLinkType.Peer" + elif link_type == "CORE": + return "ScLinkType.Core" + else: + raise Exception(f"Link type {link_type} not supported by Seed") + + def _parse_link_party(self, party): + """ + Parse link party from topo file + """ + isd_num = party.split('-')[0] + as_num = party.split(':')[2] + if "-" in as_num: + br_if = as_num.split('-')[1] + as_num = as_num.split('-')[0] + else: + br_if = as_num.split('#')[1] + as_num = as_num.split('#')[0] + return isd_num, as_num, br_if + + def _parse_links(self): + """ + Parse links from topo file + """ + links = [] + for link in self._topo_file["links"]: + (a,b,link_type, mtu, bandwidth, latency, drop) = self._read_link_properties(link) + (a_isd, a_as, a_br_if) = self._parse_link_party(a) + (b_isd, b_as, b_br_if) = self._parse_link_party(b) + + data = { + "a": (a_isd, a_as, a_br_if), + "b": (b_isd, b_as, b_br_if), + "link_type": link_type, + "mtu": mtu, + "bandwidth": bandwidth, + "latency": latency, + "drop": drop + } + + links.append(data) + return links + + def _parse_interface(self, br_if, i, ia, a_b): + """ + :param br_if: bridge interface identifier (format A#1 or 1) + :param i: link index + :param ia: ISD_AS identifier + + Parse bridge interface and update bridges data structure + """ + # create set of bridges for per AS + if "#" in br_if: + br_id = br_if.split('#')[0] + # add bridge to list if not already in list + if (br_id not in self._br[ia]): + self._br[ia].append(br_id) + else: + # if bridge does not have an ID add new ID by prepending 'A' + last_id = "" if not self._br[ia] else self._br[ia][-1] + new_id = "A"+last_id + self._br[ia].append(new_id) + # also update link data structure with new ID + isd = ia.split('_')[0] + as_num = ia.split('_')[1] + self._links[i][a_b] = (isd,as_num,new_id+"#"+br_if) + + def _parse_borderRouter_interfaces(self): + """ + generate bridge_names from links + """ + + self._br = {} + + # initialize borderRouter datastructure by creating an empty list of BorderRouters for each AS + for As in self._topo_file["ASes"]: + isd_num = As.split('-')[0] + as_num = As.split(':')[2] + ia = f"{isd_num}_{as_num}" + self._br[ia] = [] + + # parse interfaces for each link + for i in range(0,len(self._links)): + link = self._links[i] + + a_br = link['a'][2] + b_br = link['b'][2] + a_as = link['a'][1] + a_isd = link['a'][0] + b_as = link['b'][1] + b_isd = link['b'][0] + + a_ia = f"{a_isd}_{a_as}" + b_ia = f"{b_isd}_{b_as}" + + self._parse_interface(a_br, i, a_ia,"a") + self._parse_interface(b_br, i, b_ia,"b") + + # generate border router names + for ia in self._br: + br_names = [] + i = 1 + for br in self._br[ia]: + br_names.append({br: f"br{i}"}) + i += 1 + self._br[ia] = br_names + + + # replace border router interface names with border router names + for i in range(0,len(self._links)): + link = self._links[i] + a_br = link['a'][2] + b_br = link['b'][2] + a_as = link['a'][1] + a_isd = link['a'][0] + b_as = link['b'][1] + b_isd = link['b'][0] + + a_br_id = a_br.split('#')[0] + b_br_id = b_br.split('#')[0] + + for br in self._br[f"{a_isd}_{a_as}"]: + if a_br_id in br: + a_br = br[a_br_id] + break + + for br in self._br[f"{b_isd}_{b_as}"]: + if b_br_id in br: + b_br = br[b_br_id] + break + + self._links[i]['a'] = (a_isd, a_as, a_br) + self._links[i]['b'] = (b_isd, b_as, b_br) + + def _generate_addresses(self): + """ + Generate IP addresses for cross connect links + """ + self._xc_nets = CrossConnectNetAssigner() + + for i in range(0,len(self._links)): + link = self._links[i] + + a = link['a'] + b = link['b'] + + a_addr = self._xc_nets.next_addr((a,b)) + b_addr = self._xc_nets.next_addr((a,b)) + + self._links[i]['a_addr'] = a_addr + self._links[i]['b_addr'] = b_addr + def _create_AS(self): + """ + Generate code for creating ASes + """ xc_nets = CrossConnectNetAssigner() @@ -139,86 +397,76 @@ def _create_AS(self): code = "# Ases \n" - for As in self.args.topo_dicts: - as_num = As.AS().split(':')[2] - isd_num = As.ISD()[3] - is_core = True if (self.args.topo_dicts[As]["attributes"] and self.args.topo_dicts[As]["attributes"][0] == 'core') else False - # create basic As config - code += f""" -# AS-{as_num} -as{as_num} = base.createAutonomousSystem({as_num}) -scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core}) -""" - # set cert Issuer if not core AS - if not is_core: - issuer_isd_num = self.args.topo_dicts[As]["cert_issuer"].split(':')[-1] - code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={issuer_isd_num})\n" - - # create internal network - code += f"as{as_num}.createNetwork('net0')\n" - # create control Service - code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" - # create routers - border_routers = self.args.topo_dicts[As]["border_routers"] - - for router in border_routers: - br_name = "br" + router.split('-')[2] - code += f"as_{as_num}_{br_name} = as{as_num}.createRouter('{br_name}').joinNetwork('net0')\n" - # create cross connect - interfaces = border_routers[router]['interfaces'] - for interface in interfaces: - peer_as = interfaces[interface]['isd_as'].split(':')[2] - link_type = interfaces[interface]['link_to'] - remote_addr = interfaces[interface]['underlay']['remote'] - # find other AS bridge name - other_br_name = self.__other_bridge_name(remote_addr) - # generate new address because addresses form Topo-Tool dont work with seed - # always order as_nums to have unique name for both sides - if (as_num < peer_as): - addr = xc_nets.next_addr(f"{as_num}_{peer_as}") - else : - addr = xc_nets.next_addr(f"{peer_as}_{as_num}") - # generate code - code += f"as_{as_num}_{br_name}.crossConnect({peer_as},'{other_br_name}','{addr}')\n" - if ((isd_num,peer_as,as_num,link_type) not in links and link_type != "parent"): - links.append((isd_num,as_num,peer_as,link_type)) + for As in self._topo_file["ASes"]: + + (as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu) = self._parse_AS_properties(As) - code += "\n\n" + code += f"\n# AS-{as_num}\n" + code += f"as{as_num} = base.createAutonomousSystem({as_num})\n" + code += f"scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core})\n" + if cert_issuer: + code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" + if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will not set these values + code += f"as{as_num}.createNetwork('net0').setDefaultLinkProperties(latency={as_int_lat}, bandwidth={as_int_bw}, packetDrop={as_int_drop}).setMtu({as_int_mtu})\n" + else: + code += f"as{as_num}.createNetwork('net0').setDefaultLinkProperties(latency={as_int_lat}, bandwidth={as_int_bw}, packetDrop={as_int_drop})\n" - # create inter-AS links - code += "# Inter-AS routing\n" - code += self.__inter_AS_links(links) - code += "\n\n" + code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" + + # iterate through border routers + for br in self._br[f"{isd_num}_{as_num}"]: + br_name = next(iter(br.values())) + code += f"as_{as_num}_{br_name} = as{as_num}.createRouter('{br_name}').joinNetwork('net0')\n" + # create crosslinks for each border router + for link in self._links: + # check if link is connected to this AS + if link['a'][0] == isd_num and link['a'][1] == as_num: + # check if link is connected to this border router + if link['a'][2] == br_name: + b_br = link['b'][2] + b_as = link['b'][1] + a_addr = link['a_addr'] + # get link properties + latency = link['latency'] + bandwidth = link['bandwidth'] + packetDrop = link['drop'] + mtu = link['mtu'] + # generate code + if mtu: + code += f"as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n" + else: + code += f"as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n" + + if link['b'][0] == isd_num and link['b'][1] == as_num: + if link['b'][2] == br_name: + a_br = link['a'][2] + a_as = link['a'][1] + b_addr = link['b_addr'] + latency = link['latency'] + bandwidth = link['bandwidth'] + packetDrop = link['drop'] + mtu = link['mtu'] + if mtu: + code += f"as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n" + else: + code += f"as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n" return code - def __other_bridge_name(self,address): - for As in self.args.topo_dicts: - as_num = As.AS().split(':')[2] - border_routers = self.args.topo_dicts[As]["border_routers"] - for router in border_routers: - br_name = "br" + router.split('-')[2] - interfaces = border_routers[router]['interfaces'] - for interface in interfaces: - addr = interfaces[interface]['underlay']['public'] - if address == addr: - return f"br{router.split('-')[2]}" - return None - - def __inter_AS_links(self, links): - code = "" - # find link pairs - for link in links: - isd1 = link[0] - as1 = link[1] - as2 = link[2] - link_type = link[3] - # convert link types to seed format - if link_type == "child": - link_type = "Transit" - elif link_type == "core": - link_type = "Core" - elif link_type == "peer": - link_type = "Peer" - code += f"scion.addXcLink(({isd1}, {as1}), ({isd1}, {as2}), ScLinkType.{link_type})\n" - return code \ No newline at end of file + def _create_Routing(self): + """ + Generate code for creating routing + """ + code = "\n\n# Inter-AS routing\n" + + for link in self._links: + a = link['a'] + b = link['b'] + link_type = link['link_type'] + a_router = link['a'][2] + b_router = link['b'][2] + + code += f"scion.addXcLink(({a[0]},{a[1]}),({b[0]},{b[1]}),{link_type},a_router='{a_router}',b_router='{b_router}')\n" + + + return code \ No newline at end of file From 14eab06a1d03ff32b65d5439a07902faf86cbf6a Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 3 Apr 2024 17:59:42 +0200 Subject: [PATCH 10/46] added helpful description to cli arguments for disabling IPv6 check etc --- tools/topogen.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/topogen.py b/tools/topogen.py index 8f193160e6..4d97c88dd8 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -48,7 +48,8 @@ def add_arguments(parser): help='Generate a SIG per AS (only available with -d, the SIG image needs\ to be built manually e.g. when running acceptance tests)') parser.add_argument('--features', help='Feature flags to enable, a comma separated list\ - e.g. foo,bar enables foo and bar feature.') + e.g. foo,bar enables foo and bar feature.\n \ + Available features: SeedInternetMapDisable, SeedCompilerGraphviz, SeedSkipIPv6Check ') parser.add_argument('-s','--seed',action='store_true',help='Generate a seed file for the topology') return parser From cb9c80d0fc7afa3a2dab6366b2034183f2232831 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 3 Apr 2024 18:05:22 +0200 Subject: [PATCH 11/46] fixed typo --- tools/topogen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/topogen.py b/tools/topogen.py index 4d97c88dd8..f284cc1d11 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -37,7 +37,7 @@ def add_arguments(parser): parser.add_argument('-d', '--docker', action='store_true', help='Create a docker compose configuration') parser.add_argument('-n', '--network', - help='Network to create subnets in (E.g. "127.0.0.0/8"') + help='Network to create subnets in (E.g. "127.0.0.0/8")') parser.add_argument('-o', '--output-dir', default=GEN_PATH, help='Output directory') parser.add_argument('--random-ifids', action='store_true', From ddb63c3b709d7ef300e3c6857a180a0be67dc200 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 3 Apr 2024 18:13:57 +0200 Subject: [PATCH 12/46] added suport for specifying the parentNetwork for seed IPAddresses using the -n flag --- tools/topology/seed.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 20537818c2..145c369b50 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -42,8 +42,8 @@ def __init__(self, args, topo_dicts, # copyright @lschulz -- https://github.com/Bruol/seed-emulator/blob/master/examples/scion/S05-scion-internet/scion-internet.py # class to generate IP addresses for cross connect links class CrossConnectNetAssigner: - def __init__(self): - self.subnet_iter = IPv4Network("10.3.0.0/16").subnets(new_prefix=29) + def __init__(self,parentNet): + self.subnet_iter = IPv4Network(parentNet).subnets(new_prefix=29) self.xc_nets = {} def next_addr(self, net): @@ -63,6 +63,7 @@ class SeedGenerator(object): _internetMapEnabled : bool=True _SeedCompiler : str="Docker" _skipIPv6Check : bool=False + _parentNetwork : str = "10.3.0.0/16" def __init__(self, args): """ @@ -84,6 +85,9 @@ def _parseFeatures(self): self._SeedCompiler = "Graphviz" if "SeedSkipIPv6Check" in self._args.features: self._skipIPv6Check = True + if self._args.network: + self._parentNetwork = self._args.network + @@ -371,7 +375,7 @@ def _generate_addresses(self): """ Generate IP addresses for cross connect links """ - self._xc_nets = CrossConnectNetAssigner() + self._xc_nets = CrossConnectNetAssigner(self._parentNetwork) for i in range(0,len(self._links)): link = self._links[i] @@ -389,12 +393,7 @@ def _create_AS(self): """ Generate code for creating ASes """ - - xc_nets = CrossConnectNetAssigner() - - # keep track of links - links = [] - + code = "# Ases \n" for As in self._topo_file["ASes"]: From c867c0c70bd72f8c01e561183245dfdf5b5bce38 Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 5 Apr 2024 11:46:08 +0200 Subject: [PATCH 13/46] added AS note support to topo tool --- tools/topology/seed.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 145c369b50..e122692a7b 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -197,8 +197,9 @@ def _parse_AS_properties(self, As): as_int_lat = as_dict['latency'] if 'latency' in as_dict else 0 as_int_drop = as_dict['drop'] if 'drop' in as_dict else 0 as_int_mtu = as_dict['mtu'] if 'mtu' in as_dict else None + as_note = as_dict['note'] if 'note' in as_dict else None - return as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu + return as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note def _read_link_properties(self, link): """ @@ -398,10 +399,12 @@ def _create_AS(self): for As in self._topo_file["ASes"]: - (as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu) = self._parse_AS_properties(As) + (as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note) = self._parse_AS_properties(As) code += f"\n# AS-{as_num}\n" code += f"as{as_num} = base.createAutonomousSystem({as_num})\n" + if as_note: + code += f"as{as_num}.setNote('{as_note}')\n" code += f"scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core})\n" if cert_issuer: code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" From 1bb2f663f41797afa20a6a36847f435b48fa8ccd Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 5 Apr 2024 12:14:06 +0200 Subject: [PATCH 14/46] added type annotations to seed generator --- tools/topology/seed.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index e122692a7b..ff647558b1 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Mapping +from typing import Mapping, Set, Tuple, Optional, Dict, List, Union import os import subprocess from ipaddress import IPv4Network @@ -53,13 +53,13 @@ def next_addr(self, net): self.xc_nets[net] = hosts return "{}/29".format(next(self.xc_nets[net])) -class SeedGenerator(object): +class SeedGenerator(SeedGenArgs): # define class variables - _topo_file : dict + _topo_file : Dict[str,Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] # dictionary containing the topo file parsed as yaml _args : SeedGenArgs _out_file : str - _links : list - _br : dict + _links : List[Dict[str, Union[Tuple[str, str, str], str, int]]] # list of parsed links + _br : Dict[str, List[str]] _internetMapEnabled : bool=True _SeedCompiler : str="Docker" _skipIPv6Check : bool=False @@ -79,6 +79,9 @@ def __init__(self, args): self._topo_file = yaml.load(f, Loader=yaml.SafeLoader) def _parseFeatures(self): + """ + parse cli feature flags and set class flags + """ if "SeedInternetMapDisable" in self._args.features: self._internetMapEnabled = False if "SeedCompilerGraphviz" in self._args.features: @@ -88,9 +91,6 @@ def _parseFeatures(self): if self._args.network: self._parentNetwork = self._args.network - - - def generate(self): """ generate function called by ./config.py to generate seed file @@ -148,7 +148,7 @@ def generate(self): print("\n\nRunning Seed Generation\n\n") subprocess.run(["python", self._args.output_dir + "/" + SEED_CONF]) - def _isd_Set(self): + def _isd_Set(self) -> Set[str]: """ Generate a set of ISDs from the topo file """ @@ -159,7 +159,7 @@ def _isd_Set(self): isds.add(isd) return isds - def _create_ISD(self): + def _create_ISD(self) -> str: """ Generate code for creating ISDs """ @@ -181,7 +181,7 @@ def _check_IPv6(self): if network._version == 6: raise Exception("Seed does not support IPv6. Please use IPv4 only. If you want to try anyway use the feature flag SeedSkipIPv6Check.") - def _parse_AS_properties(self, As): + def _parse_AS_properties(self, As : str) -> Tuple[str,str,bool,Optional[str],int,int,int,Optional[int],Optional[str]]: """ Read AS properties from topo file """ @@ -201,7 +201,7 @@ def _parse_AS_properties(self, As): return as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note - def _read_link_properties(self, link): + def _read_link_properties(self, link : Dict[str, Union[str, Optional[int], int]]) -> Tuple[str,str,str,Optional[int],int,int,int]: """ Read link properties from topo file """ @@ -231,7 +231,7 @@ def _read_link_properties(self, link): return a, b, link_type, mtu, bandwidth, latency, drop - def _convert_link_type(self, link_type): + def _convert_link_type(self, link_type : str) -> str: """ Convert link type from topo file to seed format """ @@ -244,7 +244,7 @@ def _convert_link_type(self, link_type): else: raise Exception(f"Link type {link_type} not supported by Seed") - def _parse_link_party(self, party): + def _parse_link_party(self, party : str) -> Tuple[str,str,str]: """ Parse link party from topo file """ @@ -258,7 +258,7 @@ def _parse_link_party(self, party): as_num = as_num.split('#')[0] return isd_num, as_num, br_if - def _parse_links(self): + def _parse_links(self) -> List[Dict[str, Union[Tuple[str, str, str], str, int]]]: """ Parse links from topo file """ @@ -281,7 +281,7 @@ def _parse_links(self): links.append(data) return links - def _parse_interface(self, br_if, i, ia, a_b): + def _parse_interface(self, br_if : str, i : int , ia : str, a_b : str): """ :param br_if: bridge interface identifier (format A#1 or 1) :param i: link index @@ -390,7 +390,7 @@ def _generate_addresses(self): self._links[i]['a_addr'] = a_addr self._links[i]['b_addr'] = b_addr - def _create_AS(self): + def _create_AS(self) -> str: """ Generate code for creating ASes """ @@ -455,7 +455,7 @@ def _create_AS(self): return code - def _create_Routing(self): + def _create_Routing(self) -> str: """ Generate code for creating routing """ From e25c3a0b21b8b2dda88f21dc4ba5d81a334b6762 Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 5 Apr 2024 12:33:33 +0200 Subject: [PATCH 15/46] updated documentation for topo file --- topology/README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/topology/README.md b/topology/README.md index 13c5662945..1e520633e3 100644 --- a/topology/README.md +++ b/topology/README.md @@ -2,10 +2,34 @@ Brief description of sections in .topo files +## Table of Contents + +- [ASes](#ases-section) +- [Links](#links-section) +- [Examples](#examples-section) + +## ASes Section + The 'ASes' section describes all the ASes in a topology. You can specify different attributes like Core, MTU, certificate issuer and number of services among other things. +**Supported attributes:** +- "core" -- boolean, whether the AS is a core AS +- "voting" -- boolean +- "authoritative" -- boolean +- "issuing" -- boolean, whether the AS is an issuing AS +- "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay for now +- "cert_issuer" -- string, the issuer TRC this attribute is necessary if AS is not core +- "MTU" -- integer, the internal MTU of the AS used by seed emulator +- "latency" -- integer, the internal latency in ms of the AS used by seed emulator +- "bandwidth" -- integer, the internal bandwidth in bit/s of the AS used by seed emulator +- "drop" -- float, the internal drop rate (% in range(0.0,1.0)) of the AS used by seed emulator +- "note" -- string, a note for the AS seed emulator will include this in the beacons + + +## Links Section + The 'links' section describes the links between the BRs of different ASes. When defining the links in .topo files, we can specify whether the new interface @@ -29,3 +53,26 @@ In the example above, two links are defined resulting in: - BR 1-ff00:0:110 with a single interface - BR 1-ff00:0:120 with multiple interfaces - BR 1-ff00:0:130 with a single interface + +**Supported attributes:** +- "a" -- string, necessary, see above +- "b" -- string, necessary, see above +- "linkAtoB" -- string, necessary, the type of link, can be CORE, PEER, CHILD +- "mtu" -- integer, the MTU of the link +- "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay for now +- "bandwidth" -- integer, the bandwidth in bit/s of the link used by seed emulator +- "latency" -- integer, the latency in ms of the link used by seed emulator +- "drop" -- float, the drop rate (% in range(0.0,1.0)) of the link used by seed emulator + + +## Examples Section + +This is a list of examples: + +- [tiny.topo](tiny.topo): A simple topology with 3 ASes and 2 links. +- [tiny4.topo](tiny4.topo): same topology as tiny.topo but using IPv4. +- [wide.topo](wide.topo) +- [default.topo](default.topo) +- [default-no-peers.topo](default-no-peers.topo) +- [peering-test.topo](peering-test.topo): example with one peering link +- [peering-test-multi.topo](peering-test-multi.topo): example with multiple peering links \ No newline at end of file From c8d4d63d2a54d958cc57eeff53f67178c9276cfe Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 15 Apr 2024 11:38:42 +0200 Subject: [PATCH 16/46] added example topo files and updated .topo file documentation --- topology/README.md | 61 ++++++++++++++++++++--- topology/tiny4_link_properties.topo | 19 +++++++ topology/tiny_borderRouterProperties.topo | 41 +++++++++++++++ 3 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 topology/tiny4_link_properties.topo create mode 100644 topology/tiny_borderRouterProperties.topo diff --git a/topology/README.md b/topology/README.md index 1e520633e3..e5398d1103 100644 --- a/topology/README.md +++ b/topology/README.md @@ -4,8 +4,8 @@ Brief description of sections in .topo files ## Table of Contents -- [ASes](#ases-section) -- [Links](#links-section) +- [ASes Section](#ases-section) +- [Links Section](#links-section) - [Examples](#examples-section) ## ASes Section @@ -23,7 +23,7 @@ of services among other things. - "cert_issuer" -- string, the issuer TRC this attribute is necessary if AS is not core - "MTU" -- integer, the internal MTU of the AS used by seed emulator - "latency" -- integer, the internal latency in ms of the AS used by seed emulator -- "bandwidth" -- integer, the internal bandwidth in bit/s of the AS used by seed emulator +- "bw" -- integer, the internal bandwidth in bit/s of the AS used by seed emulator - "drop" -- float, the internal drop rate (% in range(0.0,1.0)) of the AS used by seed emulator - "note" -- string, a note for the AS seed emulator will include this in the beacons @@ -60,12 +60,59 @@ In the example above, two links are defined resulting in: - "linkAtoB" -- string, necessary, the type of link, can be CORE, PEER, CHILD - "mtu" -- integer, the MTU of the link - "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay for now -- "bandwidth" -- integer, the bandwidth in bit/s of the link used by seed emulator +- "bw" -- integer, the bandwidth in bit/s of the link used by seed emulator - "latency" -- integer, the latency in ms of the link used by seed emulator - "drop" -- float, the drop rate (% in range(0.0,1.0)) of the link used by seed emulator +## Border Router Properties Section + +The **opitonal** 'borderRouterProperties' section describes properties of BRs such as Geolocation. +Entries in the 'borderRouterProperties' section are optional. This means not every BR defined in the links section must appear in the 'borderRouterProperties' section. + +To specify a border router one can use the same string identifiers used in the link section as a key. +Though watch out as one border router can have several scion interfaces but there can only be one property section for each border router. + +Consider the following example from the *default.topo* file for clarification. In the 'links' section these 6 scion interfaces were specified: + +```yaml +"1-ff00:0:120-A#6" +"1-ff00:0:120-A#1" +"1-ff00:0:120-B#2" +"1-ff00:0:120-B#3" +"1-ff00:0:120-B#4" +"1-ff00:0:120#5" +``` + +Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. Now in the 'borderRotuerProperties' section we can specify properties for each one of the three BorderRouters like this: + +```yaml +"1-ff00:0:120#5": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "This is an arbitrary string" +"1-ff00:0:120-A#1": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "This is an arbitrary string" +"1-ff00:0:120-B#2": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "This is an arbitrary string" +``` + +Notice that instead of *"1-ff00:0:120-B#2"* we could have also specified any other interface attached to the same BorderRouter like *"1-ff00:0:120-B#3"* -## Examples Section +**Supported attributes:** +- "geo" -- the geolocation of the Border Router. geo has three arguments latitude, longitude and address. This will be added to the staticInfoConfig.json by the seed emulator if set +- "note" -- a string that can contain any string. This will be added as a note to the Border Router Node by the seed emulator + +## Examples This is a list of examples: @@ -75,4 +122,6 @@ This is a list of examples: - [default.topo](default.topo) - [default-no-peers.topo](default-no-peers.topo) - [peering-test.topo](peering-test.topo): example with one peering link -- [peering-test-multi.topo](peering-test-multi.topo): example with multiple peering links \ No newline at end of file +- [peering-test-multi.topo](peering-test-multi.topo): example with multiple peering links +- [tiny_borderRouterProperties.topo](tiny_borderRouterProperties.topo): tiny.topo example file with an example of 'borderRouterProperties' Section +- [tiny4_link_properties.topo](tiny4_link_properties.topo): tiny4.topo example file with an example of how to specify link properties for intra AS network and inter AS links \ No newline at end of file diff --git a/topology/tiny4_link_properties.topo b/topology/tiny4_link_properties.topo new file mode 100644 index 0000000000..8208fbe620 --- /dev/null +++ b/topology/tiny4_link_properties.topo @@ -0,0 +1,19 @@ +--- # Tiny Topology, IPv4 Only +ASes: + "1-ff00:0:110": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + latency: 10 + bw: 1000 + drop: 0.1 + note: "This is a core AS" + "1-ff00:0:111": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:112": + cert_issuer: 1-ff00:0:110 +links: + - {a: "1-ff00:0:110#1", b: "1-ff00:0:111#41", linkAtoB: CHILD, mtu: 1280} + - {a: "1-ff00:0:110#2", b: "1-ff00:0:112#1", linkAtoB: CHILD, bw: 500, latency: 30, drop: 0.1, mtu: 1100} diff --git a/topology/tiny_borderRouterProperties.topo b/topology/tiny_borderRouterProperties.topo new file mode 100644 index 0000000000..53f7dd3d29 --- /dev/null +++ b/topology/tiny_borderRouterProperties.topo @@ -0,0 +1,41 @@ +--- # Tiny Topology +ASes: + "1-ff00:0:110": + core: true + voting: true + authoritative: true + issuing: true + mtu: 1400 + "1-ff00:0:111": + cert_issuer: 1-ff00:0:110 + "1-ff00:0:112": + cert_issuer: 1-ff00:0:110 + underlay: UDP/IPv6 +links: + - {a: "1-ff00:0:110#1", b: "1-ff00:0:111#41", linkAtoB: CHILD, mtu: 1280} + - {a: "1-ff00:0:110#2", b: "1-ff00:0:112#1", linkAtoB: CHILD, bw: 500, underlay: UDP/IPv6} +borderRouterProperties: + "1-ff00:0:110#1": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "Hello World" + "1-ff00:0:110#2": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "Hello World" + "1-ff00:0:111#41": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "Hello World" + "1-ff00:0:112#1": + geo: + latitude: 48.858222 + longitude: 2.2945 + address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" + note: "Hello World" \ No newline at end of file From ae7679d33de54667eabe344331c616dd2b17a347 Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 15 Apr 2024 11:39:02 +0200 Subject: [PATCH 17/46] added support for optional borderRouterProperty Section in .topo file --- tools/topology/seed.py | 68 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index ff647558b1..fb368ce923 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -64,6 +64,8 @@ class SeedGenerator(SeedGenArgs): _SeedCompiler : str="Docker" _skipIPv6Check : bool=False _parentNetwork : str = "10.3.0.0/16" + _brProperties : Dict[str, Dict[str, Dict]] # dict containing maping from ISD_AS to list of border router properties + def __init__(self, args): """ @@ -120,6 +122,8 @@ def generate(self): # build appropriate link data structure self._links = self._parse_links() + self._brProperties = self._parse_borderRouterProperties() + self._parse_borderRouter_interfaces() self._generate_addresses() @@ -193,7 +197,7 @@ def _parse_AS_properties(self, As : str) -> Tuple[str,str,bool,Optional[str],int is_core = as_dict['core'] if 'core' in as_dict else False cert_issuer = as_dict['cert_issuer'].split(':')[2] if 'cert_issuer' in as_dict else None - as_int_bw = as_dict['bandwidth'] if 'bandwidth' in as_dict else 0 + as_int_bw = as_dict['bw'] if 'bw' in as_dict else 0 as_int_lat = as_dict['latency'] if 'latency' in as_dict else 0 as_int_drop = as_dict['drop'] if 'drop' in as_dict else 0 as_int_mtu = as_dict['mtu'] if 'mtu' in as_dict else None @@ -214,8 +218,8 @@ def _read_link_properties(self, link : Dict[str, Union[str, Optional[int], int]] else: mtu = None - if "bandwidth" in link: - bandwidth = link['bandwidth'] + if "bw" in link: + bandwidth = link['bw'] else: bandwidth = 0 # seed ignores value 0 @@ -300,11 +304,35 @@ def _parse_interface(self, br_if : str, i : int , ia : str, a_b : str): last_id = "" if not self._br[ia] else self._br[ia][-1] new_id = "A"+last_id self._br[ia].append(new_id) - # also update link data structure with new ID + # also update link and brProperties data structure with new ID isd = ia.split('_')[0] as_num = ia.split('_')[1] self._links[i][a_b] = (isd,as_num,new_id+"#"+br_if) + if ia in self._brProperties: + if br_if in self._brProperties[ia]: + self._brProperties[ia][new_id+"#"+br_if] = self._brProperties[ia][br_if] + del self._brProperties[ia][br_if] + + + def _parse_borderRouterProperties(self) -> Dict[str, Dict[str, Dict]]: + """ + parse BorderRouter properties from topo file + """ + + brProperties = {} + + if "borderRouterProperties" not in self._topo_file: + return brProperties + + for br in self._topo_file["borderRouterProperties"]: + (isd, as_num, br_if) = self._parse_link_party(br) + if f"{isd}_{as_num}" not in brProperties: + brProperties[f"{isd}_{as_num}"] = {} + brProperties[f"{isd}_{as_num}"][br_if] = self._topo_file["borderRouterProperties"][br] + return brProperties + + def _parse_borderRouter_interfaces(self): """ generate bridge_names from links @@ -346,7 +374,7 @@ def _parse_borderRouter_interfaces(self): self._br[ia] = br_names - # replace border router interface names with border router names + # replace border router interface names with border router names in links for i in range(0,len(self._links)): link = self._links[i] a_br = link['a'][2] @@ -371,7 +399,22 @@ def _parse_borderRouter_interfaces(self): self._links[i]['a'] = (a_isd, a_as, a_br) self._links[i]['b'] = (b_isd, b_as, b_br) + + # replace border router interface names with border router names in brProperties + + new_brProperties = {} + + for ia in self._brProperties: + new_brProperties[ia] = {} + for br_if in self._brProperties[ia]: + br_id = br_if.split('#')[0] + for br in self._br[ia]: + if br_id in br: + br_name = br[br_id] + new_brProperties[ia][br_name] = self._brProperties[ia][br_if] + self._brProperties = new_brProperties + def _generate_addresses(self): """ Generate IP addresses for cross connect links @@ -418,7 +461,20 @@ def _create_AS(self) -> str: # iterate through border routers for br in self._br[f"{isd_num}_{as_num}"]: br_name = next(iter(br.values())) - code += f"as_{as_num}_{br_name} = as{as_num}.createRouter('{br_name}').joinNetwork('net0')\n" + code += f"as_{as_num}_{br_name} = as{as_num}.createRouter('{br_name}').joinNetwork('net0')\n" + + # set border router properties + if f"{isd_num}_{as_num}" in self._brProperties and br_name in self._brProperties[f"{isd_num}_{as_num}"]: + br_props = self._brProperties[f"{isd_num}_{as_num}"][br_name] + + if "geo" in br_props: + lat = br_props['geo']['latitude'] + lon = br_props['geo']['longitude'] + addr = br_props['geo']['address'] + code += f"as_{as_num}_{br_name}.setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n" + if "note" in br_props: + code += f"as_{as_num}_{br_name}.setNote('{br_props['note']}')\n" + # create crosslinks for each border router for link in self._links: # check if link is connected to this AS From ab35e9acedfec69ee9a1ab304bdc4dc37d832729 Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 15 Apr 2024 11:41:42 +0200 Subject: [PATCH 18/46] updated .topo file documentation --- topology/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/topology/README.md b/topology/README.md index e5398d1103..f8eca2d218 100644 --- a/topology/README.md +++ b/topology/README.md @@ -6,6 +6,7 @@ Brief description of sections in .topo files - [ASes Section](#ases-section) - [Links Section](#links-section) +- [borderRouterProperties Section](#border-router-properties-section) - [Examples](#examples-section) ## ASes Section From 006336e71bf93e9c104d914f5a58da481c5821ed Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 26 Apr 2024 12:28:25 +0200 Subject: [PATCH 19/46] fixed linter errors except for long lines --- tools/topology/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/topology/config.py b/tools/topology/config.py index a1e5b9fb1c..038dd23905 100644 --- a/tools/topology/config.py +++ b/tools/topology/config.py @@ -164,7 +164,7 @@ def _generate_seed(self, topo_dicts): args = self._seed_args(topo_dicts) seed_gen = SeedGenerator(args) seed_gen.generate() - + def _seed_args(self, topo_dicts): return SeedGenArgs(self.args, topo_dicts, self.all_networks) From 56dea8c2f194060091d4efa0a8cbffb700a23cc0 Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 26 Apr 2024 12:51:53 +0200 Subject: [PATCH 20/46] linter errors in seed.py except for long lines fixed --- tools/topology/seed.py | 147 ++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 69 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index fb368ce923..b0c0b03b29 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -26,6 +26,7 @@ SEED_CONF = "scion-seed.py" + # class to manage seed arguments class SeedGenArgs(ArgsTopoDicts): def __init__(self, args, topo_dicts, @@ -41,31 +42,33 @@ def __init__(self, args, topo_dicts, # copyright @lschulz -- https://github.com/Bruol/seed-emulator/blob/master/examples/scion/S05-scion-internet/scion-internet.py # class to generate IP addresses for cross connect links + + class CrossConnectNetAssigner: - def __init__(self,parentNet): + def __init__(self, parentNet): self.subnet_iter = IPv4Network(parentNet).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) + next(hosts) # Skip first IP (reserved for Docker) self.xc_nets[net] = hosts return "{}/29".format(next(self.xc_nets[net])) + class SeedGenerator(SeedGenArgs): # define class variables - _topo_file : Dict[str,Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] # dictionary containing the topo file parsed as yaml - _args : SeedGenArgs - _out_file : str - _links : List[Dict[str, Union[Tuple[str, str, str], str, int]]] # list of parsed links - _br : Dict[str, List[str]] - _internetMapEnabled : bool=True - _SeedCompiler : str="Docker" - _skipIPv6Check : bool=False - _parentNetwork : str = "10.3.0.0/16" - _brProperties : Dict[str, Dict[str, Dict]] # dict containing maping from ISD_AS to list of border router properties - + _topo_file: Dict[str, Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] # dictionary containing the topo file parsed as yaml + _args: SeedGenArgs + _out_file: str + _links: List[Dict[str, Union[Tuple[str, str, str], str, int]]] # list of parsed links + _br: Dict[str, List[str]] + _internetMapEnabled: bool = True + _SeedCompiler: str = "Docker" + _skipIPv6Check: bool = False + _parentNetwork: str = "10.3.0.0/16" + _brProperties: Dict[str, Dict[str, Dict]] # dict containing maping from ISD_AS to list of border router properties def __init__(self, args): """ @@ -76,8 +79,8 @@ def __init__(self, args): self._args = args self._parseFeatures() - - with open(args.topo_config,"r") as f: + + with open(args.topo_config, "r") as f: self._topo_file = yaml.load(f, Loader=yaml.SafeLoader) def _parseFeatures(self): @@ -92,7 +95,7 @@ def _parseFeatures(self): self._skipIPv6Check = True if self._args.network: self._parentNetwork = self._args.network - + def generate(self): """ generate function called by ./config.py to generate seed file @@ -101,7 +104,7 @@ def generate(self): # Seed does not support IPv6 thus throw error if IPv6 is used if not self._skipIPv6Check: self._check_IPv6() - + # write header of seed file self._out_file = """ @@ -125,7 +128,7 @@ def generate(self): self._brProperties = self._parse_borderRouterProperties() self._parse_borderRouter_interfaces() - + self._generate_addresses() self._out_file += self._create_ISD() @@ -151,7 +154,7 @@ def generate(self): # generate simulation from seed file print("\n\nRunning Seed Generation\n\n") subprocess.run(["python", self._args.output_dir + "/" + SEED_CONF]) - + def _isd_Set(self) -> Set[str]: """ Generate a set of ISDs from the topo file @@ -185,16 +188,16 @@ def _check_IPv6(self): if network._version == 6: raise Exception("Seed does not support IPv6. Please use IPv4 only. If you want to try anyway use the feature flag SeedSkipIPv6Check.") - def _parse_AS_properties(self, As : str) -> Tuple[str,str,bool,Optional[str],int,int,int,Optional[int],Optional[str]]: + def _parse_AS_properties(self, As: str) -> Tuple[str, str, bool, Optional[str], int, int, int, Optional[int], Optional[str]]: """ Read AS properties from topo file """ as_num = As.split(':')[2] isd_num = As.split('-')[0] - + # handle optional properties as_dict = self._topo_file["ASes"][As] - + is_core = as_dict['core'] if 'core' in as_dict else False cert_issuer = as_dict['cert_issuer'].split(':')[2] if 'cert_issuer' in as_dict else None as_int_bw = as_dict['bw'] if 'bw' in as_dict else 0 @@ -205,7 +208,7 @@ def _parse_AS_properties(self, As : str) -> Tuple[str,str,bool,Optional[str],int return as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note - def _read_link_properties(self, link : Dict[str, Union[str, Optional[int], int]]) -> Tuple[str,str,str,Optional[int],int,int,int]: + def _read_link_properties(self, link: Dict[str, Union[str, Optional[int], int]]) -> Tuple[str, str, str, Optional[int], int, int, int]: """ Read link properties from topo file """ @@ -221,21 +224,21 @@ def _read_link_properties(self, link : Dict[str, Union[str, Optional[int], int]] if "bw" in link: bandwidth = link['bw'] else: - bandwidth = 0 # seed ignores value 0 + bandwidth = 0 # seed ignores value 0 if "latency" in link: latency = link['latency'] else: - latency = 0 # seed ignores value 0 - + latency = 0 # seed ignores value 0 + if "drop" in link: drop = link['drop'] else: - drop = 0 # seed ignores value 0 - + drop = 0 # seed ignores value 0 + return a, b, link_type, mtu, bandwidth, latency, drop - def _convert_link_type(self, link_type : str) -> str: + def _convert_link_type(self, link_type: str) -> str: """ Convert link type from topo file to seed format """ @@ -248,7 +251,7 @@ def _convert_link_type(self, link_type : str) -> str: else: raise Exception(f"Link type {link_type} not supported by Seed") - def _parse_link_party(self, party : str) -> Tuple[str,str,str]: + def _parse_link_party(self, party: str) -> Tuple[str, str, str]: """ Parse link party from topo file """ @@ -262,13 +265,13 @@ def _parse_link_party(self, party : str) -> Tuple[str,str,str]: as_num = as_num.split('#')[0] return isd_num, as_num, br_if - def _parse_links(self) -> List[Dict[str, Union[Tuple[str, str, str], str, int]]]: + def _parse_links(self) -> Dict: """ Parse links from topo file """ links = [] for link in self._topo_file["links"]: - (a,b,link_type, mtu, bandwidth, latency, drop) = self._read_link_properties(link) + (a, b, link_type, mtu, bandwidth, latency, drop) = self._read_link_properties(link) (a_isd, a_as, a_br_if) = self._parse_link_party(a) (b_isd, b_as, b_br_if) = self._parse_link_party(b) @@ -285,7 +288,7 @@ def _parse_links(self) -> List[Dict[str, Union[Tuple[str, str, str], str, int]]] links.append(data) return links - def _parse_interface(self, br_if : str, i : int , ia : str, a_b : str): + def _parse_interface(self, br_if, i, ia, a_b): """ :param br_if: bridge interface identifier (format A#1 or 1) :param i: link index @@ -296,7 +299,7 @@ def _parse_interface(self, br_if : str, i : int , ia : str, a_b : str): # create set of bridges for per AS if "#" in br_if: br_id = br_if.split('#')[0] - # add bridge to list if not already in list + # add bridge to list if not already in list if (br_id not in self._br[ia]): self._br[ia].append(br_id) else: @@ -307,13 +310,12 @@ def _parse_interface(self, br_if : str, i : int , ia : str, a_b : str): # also update link and brProperties data structure with new ID isd = ia.split('_')[0] as_num = ia.split('_')[1] - self._links[i][a_b] = (isd,as_num,new_id+"#"+br_if) + self._links[i][a_b] = (isd, as_num, new_id+"#"+br_if) if ia in self._brProperties: if br_if in self._brProperties[ia]: self._brProperties[ia][new_id+"#"+br_if] = self._brProperties[ia][br_if] del self._brProperties[ia][br_if] - def _parse_borderRouterProperties(self) -> Dict[str, Dict[str, Dict]]: """ parse BorderRouter properties from topo file @@ -323,21 +325,20 @@ def _parse_borderRouterProperties(self) -> Dict[str, Dict[str, Dict]]: if "borderRouterProperties" not in self._topo_file: return brProperties - + for br in self._topo_file["borderRouterProperties"]: (isd, as_num, br_if) = self._parse_link_party(br) if f"{isd}_{as_num}" not in brProperties: brProperties[f"{isd}_{as_num}"] = {} brProperties[f"{isd}_{as_num}"][br_if] = self._topo_file["borderRouterProperties"][br] - - return brProperties + return brProperties def _parse_borderRouter_interfaces(self): """ generate bridge_names from links """ - + self._br = {} # initialize borderRouter datastructure by creating an empty list of BorderRouters for each AS @@ -348,7 +349,7 @@ def _parse_borderRouter_interfaces(self): self._br[ia] = [] # parse interfaces for each link - for i in range(0,len(self._links)): + for i in range(0, len(self._links)): link = self._links[i] a_br = link['a'][2] @@ -358,11 +359,11 @@ def _parse_borderRouter_interfaces(self): b_as = link['b'][1] b_isd = link['b'][0] - a_ia = f"{a_isd}_{a_as}" + a_ia = f"{a_isd}_{a_as}" b_ia = f"{b_isd}_{b_as}" - - self._parse_interface(a_br, i, a_ia,"a") - self._parse_interface(b_br, i, b_ia,"b") + + self._parse_interface(a_br, i, a_ia, "a") + self._parse_interface(b_br, i, b_ia, "b") # generate border router names for ia in self._br: @@ -372,10 +373,9 @@ def _parse_borderRouter_interfaces(self): br_names.append({br: f"br{i}"}) i += 1 self._br[ia] = br_names - - + # replace border router interface names with border router names in links - for i in range(0,len(self._links)): + for i in range(0, len(self._links)): link = self._links[i] a_br = link['a'][2] b_br = link['b'][2] @@ -391,15 +391,15 @@ def _parse_borderRouter_interfaces(self): if a_br_id in br: a_br = br[a_br_id] break - + for br in self._br[f"{b_isd}_{b_as}"]: if b_br_id in br: b_br = br[b_br_id] break - + self._links[i]['a'] = (a_isd, a_as, a_br) self._links[i]['b'] = (b_isd, b_as, b_br) - + # replace border router interface names with border router names in brProperties new_brProperties = {} @@ -413,23 +413,23 @@ def _parse_borderRouter_interfaces(self): br_name = br[br_id] new_brProperties[ia][br_name] = self._brProperties[ia][br_if] - self._brProperties = new_brProperties - + self._brProperties = new_brProperties + def _generate_addresses(self): """ Generate IP addresses for cross connect links """ self._xc_nets = CrossConnectNetAssigner(self._parentNetwork) - for i in range(0,len(self._links)): + for i in range(0, len(self._links)): link = self._links[i] a = link['a'] b = link['b'] - a_addr = self._xc_nets.next_addr((a,b)) - b_addr = self._xc_nets.next_addr((a,b)) - + a_addr = self._xc_nets.next_addr((a, b)) + b_addr = self._xc_nets.next_addr((a, b)) + self._links[i]['a_addr'] = a_addr self._links[i]['b_addr'] = b_addr @@ -437,11 +437,11 @@ def _create_AS(self) -> str: """ Generate code for creating ASes """ - + code = "# Ases \n" for As in self._topo_file["ASes"]: - + (as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note) = self._parse_AS_properties(As) code += f"\n# AS-{as_num}\n" @@ -451,7 +451,7 @@ def _create_AS(self) -> str: code += f"scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core})\n" if cert_issuer: code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" - if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will not set these values + if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will not set these values code += f"as{as_num}.createNetwork('net0').setDefaultLinkProperties(latency={as_int_lat}, bandwidth={as_int_bw}, packetDrop={as_int_drop}).setMtu({as_int_mtu})\n" else: code += f"as{as_num}.createNetwork('net0').setDefaultLinkProperties(latency={as_int_lat}, bandwidth={as_int_bw}, packetDrop={as_int_drop})\n" @@ -491,10 +491,14 @@ def _create_AS(self) -> str: mtu = link['mtu'] # generate code if mtu: - code += f"as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n" + code += f""" +as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n +""" else: - code += f"as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n" - + code += f""" +as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n +""" + if link['b'][0] == isd_num and link['b'][1] == as_num: if link['b'][2] == br_name: a_br = link['a'][2] @@ -505,9 +509,13 @@ def _create_AS(self) -> str: packetDrop = link['drop'] mtu = link['mtu'] if mtu: - code += f"as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n" + code += f""" +as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n +""" else: - code += f"as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n" + code += f""" +as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n +""" return code @@ -516,7 +524,7 @@ def _create_Routing(self) -> str: Generate code for creating routing """ code = "\n\n# Inter-AS routing\n" - + for link in self._links: a = link['a'] b = link['b'] @@ -524,7 +532,8 @@ def _create_Routing(self) -> str: a_router = link['a'][2] b_router = link['b'][2] - code += f"scion.addXcLink(({a[0]},{a[1]}),({b[0]},{b[1]}),{link_type},a_router='{a_router}',b_router='{b_router}')\n" - + code += f""" +scion.addXcLink(({a[0]},{a[1]}),({b[0]},{b[1]}),{link_type},a_router='{a_router}',b_router='{b_router}')\n +""" - return code \ No newline at end of file + return code From db3e99afaba6922ff4481fcea2226af308d60707 Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 26 Apr 2024 13:57:01 +0200 Subject: [PATCH 21/46] fixed linter errors except for to long lines. Have not found good solution for this --- topology/README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/topology/README.md b/topology/README.md index f8eca2d218..429783849a 100644 --- a/topology/README.md +++ b/topology/README.md @@ -16,11 +16,12 @@ You can specify different attributes like Core, MTU, certificate issuer and numb of services among other things. **Supported attributes:** + - "core" -- boolean, whether the AS is a core AS - "voting" -- boolean - "authoritative" -- boolean - "issuing" -- boolean, whether the AS is an issuing AS -- "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay for now +- "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay - "cert_issuer" -- string, the issuer TRC this attribute is necessary if AS is not core - "MTU" -- integer, the internal MTU of the AS used by seed emulator - "latency" -- integer, the internal latency in ms of the AS used by seed emulator @@ -28,7 +29,6 @@ of services among other things. - "drop" -- float, the internal drop rate (% in range(0.0,1.0)) of the AS used by seed emulator - "note" -- string, a note for the AS seed emulator will include this in the beacons - ## Links Section The 'links' section describes the links between the BRs of different ASes. @@ -56,11 +56,12 @@ In the example above, two links are defined resulting in: - BR 1-ff00:0:130 with a single interface **Supported attributes:** + - "a" -- string, necessary, see above - "b" -- string, necessary, see above - "linkAtoB" -- string, necessary, the type of link, can be CORE, PEER, CHILD - "mtu" -- integer, the MTU of the link -- "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay for now +- "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed doesn't support IPv6 - "bw" -- integer, the bandwidth in bit/s of the link used by seed emulator - "latency" -- integer, the latency in ms of the link used by seed emulator - "drop" -- float, the drop rate (% in range(0.0,1.0)) of the link used by seed emulator @@ -70,7 +71,7 @@ In the example above, two links are defined resulting in: The **opitonal** 'borderRouterProperties' section describes properties of BRs such as Geolocation. Entries in the 'borderRouterProperties' section are optional. This means not every BR defined in the links section must appear in the 'borderRouterProperties' section. -To specify a border router one can use the same string identifiers used in the link section as a key. +To specify a border router one can use the same string identifiers used in the link section as a key. Though watch out as one border router can have several scion interfaces but there can only be one property section for each border router. Consider the following example from the *default.topo* file for clarification. In the 'links' section these 6 scion interfaces were specified: @@ -78,7 +79,7 @@ Consider the following example from the *default.topo* file for clarification. I ```yaml "1-ff00:0:120-A#6" "1-ff00:0:120-A#1" -"1-ff00:0:120-B#2" +"1-ff00:0:120-B#2" "1-ff00:0:120-B#3" "1-ff00:0:120-B#4" "1-ff00:0:120#5" @@ -99,7 +100,7 @@ Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. longitude: 2.2945 address: "Eiffel Tower\n7th arrondissement\nParis\nFrance" note: "This is an arbitrary string" -"1-ff00:0:120-B#2": +"1-ff00:0:120-B#2": geo: latitude: 48.858222 longitude: 2.2945 @@ -110,13 +111,14 @@ Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. Notice that instead of *"1-ff00:0:120-B#2"* we could have also specified any other interface attached to the same BorderRouter like *"1-ff00:0:120-B#3"* **Supported attributes:** + - "geo" -- the geolocation of the Border Router. geo has three arguments latitude, longitude and address. This will be added to the staticInfoConfig.json by the seed emulator if set -- "note" -- a string that can contain any string. This will be added as a note to the Border Router Node by the seed emulator +- "note" -- a string that can contain any string. This will be added as a note to the Border Router Node by the seed emulator ## Examples This is a list of examples: - + - [tiny.topo](tiny.topo): A simple topology with 3 ASes and 2 links. - [tiny4.topo](tiny4.topo): same topology as tiny.topo but using IPv4. - [wide.topo](wide.topo) From db7fe421fdde5181f20421c1483fcecc17a462e3 Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 17 May 2024 13:58:28 +0200 Subject: [PATCH 22/46] added all but one of the review suggestions --- tools/topogen.py | 2 +- tools/topology/seed.py | 29 ++++++++------------- topology/README.md | 31 +++++++++++++---------- topology/tiny4_link_properties.topo | 2 +- topology/tiny_borderRouterProperties.topo | 2 +- 5 files changed, 31 insertions(+), 35 deletions(-) diff --git a/tools/topogen.py b/tools/topogen.py index 67dbb444de..fe04b675b7 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -49,10 +49,10 @@ def add_arguments(parser): parser.add_argument('--sig', action='store_true', help='Generate a SIG per AS (only available with -d, the SIG image needs\ to be built manually e.g. when running acceptance tests)') + parser.add_argument('-s','--seed',action='store_true',help='Generate a seed file for the topology') parser.add_argument('--features', help='Feature flags to enable, a comma separated list\ e.g. foo,bar enables foo and bar feature.\n \ Available features: SeedInternetMapDisable, SeedCompilerGraphviz, SeedSkipIPv6Check ') - parser.add_argument('-s','--seed',action='store_true',help='Generate a seed file for the topology') return parser diff --git a/tools/topology/seed.py b/tools/topology/seed.py index b0c0b03b29..e024b11f48 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -68,7 +68,7 @@ class SeedGenerator(SeedGenArgs): _SeedCompiler: str = "Docker" _skipIPv6Check: bool = False _parentNetwork: str = "10.3.0.0/16" - _brProperties: Dict[str, Dict[str, Dict]] # dict containing maping from ISD_AS to list of border router properties + _brProperties: Dict[str, Dict[str, Dict]] # dict containing mapping from ISD_AS to list of border router properties def __init__(self, args): """ @@ -265,7 +265,7 @@ def _parse_link_party(self, party: str) -> Tuple[str, str, str]: as_num = as_num.split('#')[0] return isd_num, as_num, br_if - def _parse_links(self) -> Dict: + def _parse_links(self) -> List[Dict[str, Union[Tuple[str, str, str], str, int]]]: """ Parse links from topo file """ @@ -352,12 +352,8 @@ def _parse_borderRouter_interfaces(self): for i in range(0, len(self._links)): link = self._links[i] - a_br = link['a'][2] - b_br = link['b'][2] - a_as = link['a'][1] - a_isd = link['a'][0] - b_as = link['b'][1] - b_isd = link['b'][0] + a_isd, a_as, a_br = link['a'] + b_isd, b_as, b_br = link['b'] a_ia = f"{a_isd}_{a_as}" b_ia = f"{b_isd}_{b_as}" @@ -377,13 +373,10 @@ def _parse_borderRouter_interfaces(self): # replace border router interface names with border router names in links for i in range(0, len(self._links)): link = self._links[i] - a_br = link['a'][2] - b_br = link['b'][2] - a_as = link['a'][1] - a_isd = link['a'][0] - b_as = link['b'][1] - b_isd = link['b'][0] + a_isd, a_as, a_br = link['a'] + b_isd, b_as, b_br = link['b'] + a_br_id = a_br.split('#')[0] b_br_id = b_br.split('#')[0] @@ -402,18 +395,18 @@ def _parse_borderRouter_interfaces(self): # replace border router interface names with border router names in brProperties - new_brProperties = {} + new_br_properties = {} for ia in self._brProperties: - new_brProperties[ia] = {} + new_br_properties[ia] = {} for br_if in self._brProperties[ia]: br_id = br_if.split('#')[0] for br in self._br[ia]: if br_id in br: br_name = br[br_id] - new_brProperties[ia][br_name] = self._brProperties[ia][br_if] + new_br_properties[ia][br_name] = self._brProperties[ia][br_if] - self._brProperties = new_brProperties + self._brProperties = new_br_properties def _generate_addresses(self): """ diff --git a/topology/README.md b/topology/README.md index 429783849a..4e54b00638 100644 --- a/topology/README.md +++ b/topology/README.md @@ -7,7 +7,7 @@ Brief description of sections in .topo files - [ASes Section](#ases-section) - [Links Section](#links-section) - [borderRouterProperties Section](#border-router-properties-section) -- [Examples](#examples-section) +- [Examples](#examples) ## ASes Section @@ -22,13 +22,15 @@ of services among other things. - "authoritative" -- boolean - "issuing" -- boolean, whether the AS is an issuing AS - "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed does not support IPv6 underlay -- "cert_issuer" -- string, the issuer TRC this attribute is necessary if AS is not core -- "MTU" -- integer, the internal MTU of the AS used by seed emulator +- "cert_issuer" -- string, the issuer IA of the CA. This attribute is necessary if AS is not core +- "MTU" -- integer, the internal MTU of the AS * - "latency" -- integer, the internal latency in ms of the AS used by seed emulator - "bw" -- integer, the internal bandwidth in bit/s of the AS used by seed emulator - "drop" -- float, the internal drop rate (% in range(0.0,1.0)) of the AS used by seed emulator - "note" -- string, a note for the AS seed emulator will include this in the beacons +Fields marked with * are used by the seed emulator for setting link properties. + ## Links Section The 'links' section describes the links between the BRs of different ASes. @@ -57,22 +59,23 @@ In the example above, two links are defined resulting in: **Supported attributes:** -- "a" -- string, necessary, see above -- "b" -- string, necessary, see above -- "linkAtoB" -- string, necessary, the type of link, can be CORE, PEER, CHILD -- "mtu" -- integer, the MTU of the link +- "a" -- string, mandatory, see above +- "b" -- string, mandatory, see above +- "linkAtoB" -- string, mandatory, the type of link, can be CORE, PEER, CHILD +- "mtu" -- integer, the MTU of the link * - "underlay" -- default is UDP/IPv4, can be set to UDP/IPv6, seed doesn't support IPv6 -- "bw" -- integer, the bandwidth in bit/s of the link used by seed emulator -- "latency" -- integer, the latency in ms of the link used by seed emulator -- "drop" -- float, the drop rate (% in range(0.0,1.0)) of the link used by seed emulator +- "bw" -- integer, the bandwidth in bit/s of the link * +- "latency" -- integer, the latency in ms of the link * +- "drop" -- float, the drop rate (% in range(0.0,1.0)) of the link * + +Fields marked with * are used by the seed emulator for setting link properties. ## Border Router Properties Section -The **opitonal** 'borderRouterProperties' section describes properties of BRs such as Geolocation. +The **optional** 'borderRouterProperties' section describes properties of BRs such as Geolocation. Entries in the 'borderRouterProperties' section are optional. This means not every BR defined in the links section must appear in the 'borderRouterProperties' section. -To specify a border router one can use the same string identifiers used in the link section as a key. -Though watch out as one border router can have several scion interfaces but there can only be one property section for each border router. +The same string identifiers as in the link section specify the key for a border router. Though watch out as one border router can have several SCION interfaces but there can only be one property section for each border router. Consider the following example from the *default.topo* file for clarification. In the 'links' section these 6 scion interfaces were specified: @@ -85,7 +88,7 @@ Consider the following example from the *default.topo* file for clarification. I "1-ff00:0:120#5" ``` -Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. Now in the 'borderRotuerProperties' section we can specify properties for each one of the three BorderRouters like this: +Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. Now in the 'borderRouterProperties' section we can specify properties for each one of the three BorderRouters like this: ```yaml "1-ff00:0:120#5": diff --git a/topology/tiny4_link_properties.topo b/topology/tiny4_link_properties.topo index 8208fbe620..95d0fbe614 100644 --- a/topology/tiny4_link_properties.topo +++ b/topology/tiny4_link_properties.topo @@ -1,4 +1,4 @@ ---- # Tiny Topology, IPv4 Only +--- # Tiny Topology with link properties, IPv4 Only ASes: "1-ff00:0:110": core: true diff --git a/topology/tiny_borderRouterProperties.topo b/topology/tiny_borderRouterProperties.topo index 53f7dd3d29..27915e2662 100644 --- a/topology/tiny_borderRouterProperties.topo +++ b/topology/tiny_borderRouterProperties.topo @@ -1,4 +1,4 @@ ---- # Tiny Topology +--- # Tiny Topology with border router properties ASes: "1-ff00:0:110": core: true From 401f7d93ae2133af2c7f10ac4699c1c11686997e Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 13:35:50 +0200 Subject: [PATCH 23/46] fixed linter errors in README --- topology/README.md | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/topology/README.md b/topology/README.md index 4e54b00638..6af7ad0971 100644 --- a/topology/README.md +++ b/topology/README.md @@ -73,11 +73,16 @@ Fields marked with * are used by the seed emulator for setting link properties. ## Border Router Properties Section The **optional** 'borderRouterProperties' section describes properties of BRs such as Geolocation. -Entries in the 'borderRouterProperties' section are optional. This means not every BR defined in the links section must appear in the 'borderRouterProperties' section. +Entries in the 'borderRouterProperties' section are optional. +This means not every BR defined in the links section must appear in the +'borderRouterProperties' section. -The same string identifiers as in the link section specify the key for a border router. Though watch out as one border router can have several SCION interfaces but there can only be one property section for each border router. +The same string identifiers as in the link section specify the key for a border router. +Though watch out as one border router can have several +SCION interfaces but there can only be one property section for each border router. -Consider the following example from the *default.topo* file for clarification. In the 'links' section these 6 scion interfaces were specified: +Consider the following example from the *default.topo* file for clarification. +In the 'links' section these 6 scion interfaces were specified: ```yaml "1-ff00:0:120-A#6" @@ -88,7 +93,9 @@ Consider the following example from the *default.topo* file for clarification. I "1-ff00:0:120#5" ``` -Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. Now in the 'borderRouterProperties' section we can specify properties for each one of the three BorderRouters like this: +Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. +Now in the 'borderRouterProperties' section we can specify properties for each one +of the three BorderRouters like this: ```yaml "1-ff00:0:120#5": @@ -111,12 +118,17 @@ Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. note: "This is an arbitrary string" ``` -Notice that instead of *"1-ff00:0:120-B#2"* we could have also specified any other interface attached to the same BorderRouter like *"1-ff00:0:120-B#3"* +Notice that instead of *"1-ff00:0:120-B#2"* +we could have also specified any other interface attached +to the same BorderRouter like *"1-ff00:0:120-B#3"* **Supported attributes:** -- "geo" -- the geolocation of the Border Router. geo has three arguments latitude, longitude and address. This will be added to the staticInfoConfig.json by the seed emulator if set -- "note" -- a string that can contain any string. This will be added as a note to the Border Router Node by the seed emulator +- "geo" -- the geolocation of the Border Router. +geo has three arguments latitude, longitude and address. +This will be added to the staticInfoConfig.json by the seed emulator if set +- "note" -- a string that can contain any string. +This will be added as a note to the Border Router Node by the seed emulator ## Examples @@ -129,5 +141,8 @@ This is a list of examples: - [default-no-peers.topo](default-no-peers.topo) - [peering-test.topo](peering-test.topo): example with one peering link - [peering-test-multi.topo](peering-test-multi.topo): example with multiple peering links -- [tiny_borderRouterProperties.topo](tiny_borderRouterProperties.topo): tiny.topo example file with an example of 'borderRouterProperties' Section -- [tiny4_link_properties.topo](tiny4_link_properties.topo): tiny4.topo example file with an example of how to specify link properties for intra AS network and inter AS links \ No newline at end of file +- [tiny_borderRouterProperties.topo](tiny_borderRouterProperties.topo): +tiny.topo example file with an example of 'borderRouterProperties' Section +- [tiny4_link_properties.topo](tiny4_link_properties.topo): +tiny4.topo example file with an example of how to specify link properties for intra AS network +and inter AS links From 34c6c0eb77918f941f809d9c56c7c76bea2cae0d Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 13:57:19 +0200 Subject: [PATCH 24/46] fixed linter errors in readme --- topology/README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/topology/README.md b/topology/README.md index 6af7ad0971..d25dd21164 100644 --- a/topology/README.md +++ b/topology/README.md @@ -73,15 +73,15 @@ Fields marked with * are used by the seed emulator for setting link properties. ## Border Router Properties Section The **optional** 'borderRouterProperties' section describes properties of BRs such as Geolocation. -Entries in the 'borderRouterProperties' section are optional. -This means not every BR defined in the links section must appear in the +Entries in the 'borderRouterProperties' section are optional. +This means not every BR defined in the links section must appear in the 'borderRouterProperties' section. -The same string identifiers as in the link section specify the key for a border router. -Though watch out as one border router can have several +The same string identifiers as in the link section specify the key for a border router. +Though watch out as one border router can have several SCION interfaces but there can only be one property section for each border router. -Consider the following example from the *default.topo* file for clarification. +Consider the following example from the *default.topo* file for clarification. In the 'links' section these 6 scion interfaces were specified: ```yaml @@ -93,8 +93,8 @@ In the 'links' section these 6 scion interfaces were specified: "1-ff00:0:120#5" ``` -Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. -Now in the 'borderRouterProperties' section we can specify properties for each one +Notice though how the 6 scion interfaces are connected to only 3 BorderRouters. +Now in the 'borderRouterProperties' section we can specify properties for each one of the three BorderRouters like this: ```yaml @@ -118,16 +118,16 @@ of the three BorderRouters like this: note: "This is an arbitrary string" ``` -Notice that instead of *"1-ff00:0:120-B#2"* -we could have also specified any other interface attached +Notice that instead of *"1-ff00:0:120-B#2"* +we could have also specified any other interface attached to the same BorderRouter like *"1-ff00:0:120-B#3"* **Supported attributes:** -- "geo" -- the geolocation of the Border Router. -geo has three arguments latitude, longitude and address. +- "geo" -- the geolocation of the Border Router. +geo has three arguments latitude, longitude and address. This will be added to the staticInfoConfig.json by the seed emulator if set -- "note" -- a string that can contain any string. +- "note" -- a string that can contain any string. This will be added as a note to the Border Router Node by the seed emulator ## Examples @@ -141,8 +141,8 @@ This is a list of examples: - [default-no-peers.topo](default-no-peers.topo) - [peering-test.topo](peering-test.topo): example with one peering link - [peering-test-multi.topo](peering-test-multi.topo): example with multiple peering links -- [tiny_borderRouterProperties.topo](tiny_borderRouterProperties.topo): +- [tiny_borderRouterProperties.topo](tiny_borderRouterProperties.topo): tiny.topo example file with an example of 'borderRouterProperties' Section -- [tiny4_link_properties.topo](tiny4_link_properties.topo): -tiny4.topo example file with an example of how to specify link properties for intra AS network +- [tiny4_link_properties.topo](tiny4_link_properties.topo): +tiny4.topo example file with an example of how to specify link properties for intra AS network and inter AS links From f0928ecf7a191958a6fa652947f7f2eee416d15a Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 14:41:45 +0200 Subject: [PATCH 25/46] tried to fix linter errors --- tools/topology/seed.py | 110 ++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index e024b11f48..ec77969039 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -40,7 +40,8 @@ def __init__(self, args, topo_dicts, self.networks = networks -# copyright @lschulz -- https://github.com/Bruol/seed-emulator/blob/master/examples/scion/S05-scion-internet/scion-internet.py +# copyright +# @lschulz -- seed-emulator/examples/scion/S05-scion-internet/scion-internet.py # class to generate IP addresses for cross connect links @@ -59,7 +60,10 @@ def next_addr(self, net): class SeedGenerator(SeedGenArgs): # define class variables - _topo_file: Dict[str, Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] # dictionary containing the topo file parsed as yaml + # dictionary containing the topo file parsed as yaml + _topo_file: \ + Dict[str, \ + Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] _args: SeedGenArgs _out_file: str _links: List[Dict[str, Union[Tuple[str, str, str], str, int]]] # list of parsed links @@ -68,7 +72,8 @@ class SeedGenerator(SeedGenArgs): _SeedCompiler: str = "Docker" _skipIPv6Check: bool = False _parentNetwork: str = "10.3.0.0/16" - _brProperties: Dict[str, Dict[str, Dict]] # dict containing mapping from ISD_AS to list of border router properties + # dict containing mapping from ISD_AS to list of border router properties + _brProperties: Dict[str, Dict[str, Dict]] def __init__(self, args): """ @@ -147,7 +152,8 @@ def generate(self): emu.render() # Compilation -emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}), './{self._args.output_dir}/seed-compiled') +emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}), \ +'./{self._args.output_dir}/seed-compiled') """ # write seed file write_file(os.path.join(self._args.output_dir, SEED_CONF), self._out_file) @@ -186,9 +192,12 @@ def _check_IPv6(self): """ for network in self._args.networks: if network._version == 6: - raise Exception("Seed does not support IPv6. Please use IPv4 only. If you want to try anyway use the feature flag SeedSkipIPv6Check.") + raise Exception(( + "Seed does not support IPv6. Please use IPv4 only. " + "If you want to try anyway use the feature flag SeedSkipIPv6Check.")) - def _parse_AS_properties(self, As: str) -> Tuple[str, str, bool, Optional[str], int, int, int, Optional[int], Optional[str]]: + def _parse_AS_properties(self, As: str)\ + -> Tuple[str, str, bool, Optional[str], int, int, int, Optional[int], Optional[str]]: """ Read AS properties from topo file """ @@ -206,9 +215,20 @@ def _parse_AS_properties(self, As: str) -> Tuple[str, str, bool, Optional[str], as_int_mtu = as_dict['mtu'] if 'mtu' in as_dict else None as_note = as_dict['note'] if 'note' in as_dict else None - return as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note + res = (as_num, + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) - def _read_link_properties(self, link: Dict[str, Union[str, Optional[int], int]]) -> Tuple[str, str, str, Optional[int], int, int, int]: + return res + + def _read_link_properties(self, link: Dict[str, Union[str, Optional[int], int]]) \ + -> Tuple[str, str, str, Optional[int], int, int, int]: """ Read link properties from topo file """ @@ -341,7 +361,8 @@ def _parse_borderRouter_interfaces(self): self._br = {} - # initialize borderRouter datastructure by creating an empty list of BorderRouters for each AS + # initialize borderRouter datastructure + # by creating an empty list of BorderRouters for each AS for As in self._topo_file["ASes"]: isd_num = As.split('-')[0] as_num = As.split(':')[2] @@ -376,7 +397,7 @@ def _parse_borderRouter_interfaces(self): a_isd, a_as, a_br = link['a'] b_isd, b_as, b_br = link['b'] - + a_br_id = a_br.split('#')[0] b_br_id = b_br.split('#')[0] @@ -435,7 +456,15 @@ def _create_AS(self) -> str: for As in self._topo_file["ASes"]: - (as_num, isd_num, is_core, cert_issuer, as_int_bw, as_int_lat, as_int_drop, as_int_mtu, as_note) = self._parse_AS_properties(As) + (as_num, + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) = self._parse_AS_properties(As) code += f"\n# AS-{as_num}\n" code += f"as{as_num} = base.createAutonomousSystem({as_num})\n" @@ -444,27 +473,39 @@ def _create_AS(self) -> str: code += f"scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core})\n" if cert_issuer: code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" - if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will not set these values - code += f"as{as_num}.createNetwork('net0').setDefaultLinkProperties(latency={as_int_lat}, bandwidth={as_int_bw}, packetDrop={as_int_drop}).setMtu({as_int_mtu})\n" + if as_int_mtu: #default value 0 for latency, bandwidth, packetDrop will be ignored + code += (f"as{as_num}.createNetwork('net0')" + f".setDefaultLinkProperties(" + f"latency={as_int_lat}," + f"bandwidth={as_int_bw}," + f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") else: - code += f"as{as_num}.createNetwork('net0').setDefaultLinkProperties(latency={as_int_lat}, bandwidth={as_int_bw}, packetDrop={as_int_drop})\n" + code += (f"as{as_num}.createNetwork('net0')" + f".setDefaultLinkProperties(" + f"latency={as_int_lat}, " + f"bandwidth={as_int_bw}, " + f"packetDrop={as_int_drop})\n") code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" # iterate through border routers for br in self._br[f"{isd_num}_{as_num}"]: br_name = next(iter(br.values())) - code += f"as_{as_num}_{br_name} = as{as_num}.createRouter('{br_name}').joinNetwork('net0')\n" + code += (f"as_{as_num}_{br_name} = as{as_num}" + f".createRouter('{br_name}')" + f".joinNetwork('net0')\n") # set border router properties - if f"{isd_num}_{as_num}" in self._brProperties and br_name in self._brProperties[f"{isd_num}_{as_num}"]: + if f"{isd_num}_{as_num}" in self._brProperties \ + and br_name in self._brProperties[f"{isd_num}_{as_num}"]: br_props = self._brProperties[f"{isd_num}_{as_num}"][br_name] if "geo" in br_props: lat = br_props['geo']['latitude'] lon = br_props['geo']['longitude'] addr = br_props['geo']['address'] - code += f"as_{as_num}_{br_name}.setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n" + code += (f"as_{as_num}_{br_name}" + f".setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n") if "note" in br_props: code += f"as_{as_num}_{br_name}.setNote('{br_props['note']}')\n" @@ -484,13 +525,15 @@ def _create_AS(self) -> str: mtu = link['mtu'] # generate code if mtu: - code += f""" -as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n -""" + code += (f"as_{as_num}_{br_name}" + f".crossConnect({b_as},'{b_br}','{a_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop},MTU={mtu})\n") else: - code += f""" -as_{as_num}_{br_name}.crossConnect({b_as},'{b_br}','{a_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n -""" + code += (f"as_{as_num}_{br_name}" + f".crossConnect({b_as},'{b_br}','{a_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop})\n") if link['b'][0] == isd_num and link['b'][1] == as_num: if link['b'][2] == br_name: @@ -502,14 +545,15 @@ def _create_AS(self) -> str: packetDrop = link['drop'] mtu = link['mtu'] if mtu: - code += f""" -as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop},MTU={mtu})\n -""" + code += (f"as_{as_num}_{br_name}" + f".crossConnect({a_as},'{a_br}','{b_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop},MTU={mtu})\n") else: - code += f""" -as_{as_num}_{br_name}.crossConnect({a_as},'{a_br}','{b_addr}',latency={latency},bandwidth={bandwidth},packetDrop={packetDrop})\n -""" - + code += (f"as_{as_num}_{br_name}" + f".crossConnect({a_as},'{a_br}','{b_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop})\n") return code def _create_Routing(self) -> str: @@ -525,8 +569,6 @@ def _create_Routing(self) -> str: a_router = link['a'][2] b_router = link['b'][2] - code += f""" -scion.addXcLink(({a[0]},{a[1]}),({b[0]},{b[1]}),{link_type},a_router='{a_router}',b_router='{b_router}')\n -""" - + code += (f"scion.addXcLink(({a[0]},{a[1]}),({b[0]},{b[1]})," + f"{link_type},a_router='{a_router}',b_router='{b_router}')\n") return code From 9e421b7f44901268d667203ed8083b7d2f66aaf9 Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 15:02:16 +0200 Subject: [PATCH 26/46] tried to fix linter errors --- tools/topology/seed.py | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index ec77969039..a4322be13c 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -40,7 +40,7 @@ def __init__(self, args, topo_dicts, self.networks = networks -# copyright +# copyright # @lschulz -- seed-emulator/examples/scion/S05-scion-internet/scion-internet.py # class to generate IP addresses for cross connect links @@ -62,8 +62,8 @@ class SeedGenerator(SeedGenArgs): # define class variables # dictionary containing the topo file parsed as yaml _topo_file: \ - Dict[str, \ - Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] + Dict[str, + Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] _args: SeedGenArgs _out_file: str _links: List[Dict[str, Union[Tuple[str, str, str], str, int]]] # list of parsed links @@ -73,7 +73,7 @@ class SeedGenerator(SeedGenArgs): _skipIPv6Check: bool = False _parentNetwork: str = "10.3.0.0/16" # dict containing mapping from ISD_AS to list of border router properties - _brProperties: Dict[str, Dict[str, Dict]] + _brProperties: Dict[str, Dict[str, Dict]] def __init__(self, args): """ @@ -216,19 +216,19 @@ def _parse_AS_properties(self, As: str)\ as_note = as_dict['note'] if 'note' in as_dict else None res = (as_num, - isd_num, - is_core, - cert_issuer, - as_int_bw, - as_int_lat, - as_int_drop, - as_int_mtu, - as_note) + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) return res def _read_link_properties(self, link: Dict[str, Union[str, Optional[int], int]]) \ - -> Tuple[str, str, str, Optional[int], int, int, int]: + -> Tuple[str, str, str, Optional[int], int, int, int]: """ Read link properties from topo file """ @@ -361,7 +361,7 @@ def _parse_borderRouter_interfaces(self): self._br = {} - # initialize borderRouter datastructure + # initialize borderRouter datastructure # by creating an empty list of BorderRouters for each AS for As in self._topo_file["ASes"]: isd_num = As.split('-')[0] @@ -456,15 +456,15 @@ def _create_AS(self) -> str: for As in self._topo_file["ASes"]: - (as_num, - isd_num, - is_core, - cert_issuer, - as_int_bw, - as_int_lat, - as_int_drop, - as_int_mtu, - as_note) = self._parse_AS_properties(As) + (as_num, + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) = self._parse_AS_properties(As) code += f"\n# AS-{as_num}\n" code += f"as{as_num} = base.createAutonomousSystem({as_num})\n" @@ -473,18 +473,18 @@ def _create_AS(self) -> str: code += f"scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core})\n" if cert_issuer: code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" - if as_int_mtu: #default value 0 for latency, bandwidth, packetDrop will be ignored + if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored code += (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}," - f"bandwidth={as_int_bw}," - f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") + f".setDefaultLinkProperties(" + f"latency={as_int_lat}," + f"bandwidth={as_int_bw}," + f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") else: code += (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}, " - f"bandwidth={as_int_bw}, " - f"packetDrop={as_int_drop})\n") + f".setDefaultLinkProperties(" + f"latency={as_int_lat}, " + f"bandwidth={as_int_bw}, " + f"packetDrop={as_int_drop})\n") code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" @@ -492,12 +492,12 @@ def _create_AS(self) -> str: for br in self._br[f"{isd_num}_{as_num}"]: br_name = next(iter(br.values())) code += (f"as_{as_num}_{br_name} = as{as_num}" - f".createRouter('{br_name}')" - f".joinNetwork('net0')\n") + f".createRouter('{br_name}')" + f".joinNetwork('net0')\n") # set border router properties if f"{isd_num}_{as_num}" in self._brProperties \ - and br_name in self._brProperties[f"{isd_num}_{as_num}"]: + and br_name in self._brProperties[f"{isd_num}_{as_num}"]: br_props = self._brProperties[f"{isd_num}_{as_num}"][br_name] if "geo" in br_props: From 53f0e8e2ca750fbbbc14601d7278ccab12799dbb Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 15:25:04 +0200 Subject: [PATCH 27/46] try indentation --- tools/topology/seed.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index a4322be13c..10dc342223 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -492,8 +492,8 @@ def _create_AS(self) -> str: for br in self._br[f"{isd_num}_{as_num}"]: br_name = next(iter(br.values())) code += (f"as_{as_num}_{br_name} = as{as_num}" - f".createRouter('{br_name}')" - f".joinNetwork('net0')\n") + f".createRouter('{br_name}')" + f".joinNetwork('net0')\n") # set border router properties if f"{isd_num}_{as_num}" in self._brProperties \ From faf4fa901633716de4fd7cc64d50919219c1c2a5 Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 15:34:59 +0200 Subject: [PATCH 28/46] tried to fix linter errors --- tools/topology/seed.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 10dc342223..d07305392f 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -63,7 +63,7 @@ class SeedGenerator(SeedGenArgs): # dictionary containing the topo file parsed as yaml _topo_file: \ Dict[str, - Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] + Union[Dict[str, Dict[str, Union[bool, int, str]]], List[Dict[str, Union[str, int]]]]] _args: SeedGenArgs _out_file: str _links: List[Dict[str, Union[Tuple[str, str, str], str, int]]] # list of parsed links @@ -216,14 +216,14 @@ def _parse_AS_properties(self, As: str)\ as_note = as_dict['note'] if 'note' in as_dict else None res = (as_num, - isd_num, - is_core, - cert_issuer, - as_int_bw, - as_int_lat, - as_int_drop, - as_int_mtu, - as_note) + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) return res @@ -475,16 +475,16 @@ def _create_AS(self) -> str: code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored code += (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}," - f"bandwidth={as_int_bw}," - f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") + f".setDefaultLinkProperties(" + f"latency={as_int_lat}," + f"bandwidth={as_int_bw}," + f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") else: code += (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}, " - f"bandwidth={as_int_bw}, " - f"packetDrop={as_int_drop})\n") + f".setDefaultLinkProperties(" + f"latency={as_int_lat}, " + f"bandwidth={as_int_bw}, " + f"packetDrop={as_int_drop})\n") code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" From 613acd6f4e1235c9c8ca52eae583d2ff5f1a7090 Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 15:40:09 +0200 Subject: [PATCH 29/46] tried to fix linter errors --- tools/topology/seed.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index d07305392f..43b718cb52 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -216,14 +216,14 @@ def _parse_AS_properties(self, As: str)\ as_note = as_dict['note'] if 'note' in as_dict else None res = (as_num, - isd_num, - is_core, - cert_issuer, - as_int_bw, - as_int_lat, - as_int_drop, - as_int_mtu, - as_note) + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) return res From bdb4f2798ee9168e58165548d719891319340a1b Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 15:43:27 +0200 Subject: [PATCH 30/46] tried to fix linter errors --- tools/topology/seed.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 43b718cb52..5883f0b22f 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -216,14 +216,14 @@ def _parse_AS_properties(self, As: str)\ as_note = as_dict['note'] if 'note' in as_dict else None res = (as_num, - isd_num, - is_core, - cert_issuer, - as_int_bw, - as_int_lat, - as_int_drop, + isd_num, + is_core, + cert_issuer, + as_int_bw, + as_int_lat, + as_int_drop, as_int_mtu, - as_note) + as_note) return res From 7836073c150521959eb4507d5107be112863ee1a Mon Sep 17 00:00:00 2001 From: bruol Date: Sat, 18 May 2024 15:45:43 +0200 Subject: [PATCH 31/46] should have fixed the linter errors --- tools/topology/seed.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 5883f0b22f..1c03e63a73 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -216,14 +216,14 @@ def _parse_AS_properties(self, As: str)\ as_note = as_dict['note'] if 'note' in as_dict else None res = (as_num, - isd_num, - is_core, - cert_issuer, + isd_num, + is_core, + cert_issuer, as_int_bw, - as_int_lat, - as_int_drop, - as_int_mtu, - as_note) + as_int_lat, + as_int_drop, + as_int_mtu, + as_note) return res From 3003d64f4d6d02a376f23fb8b790370b5cd39a1e Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 3 Jun 2024 11:10:54 +0200 Subject: [PATCH 32/46] 1) implemented review to put seed AS generation in template 2) added OSPF to seed emulation to make specific topologies work 3) added dump feature to emulation to dump emulation before rendering --- tools/topology/seed.py | 79 ++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 1c03e63a73..9746f80f00 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -115,7 +115,7 @@ def generate(self): from seedemu.compiler import Docker from seedemu.core import Emulator -from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion +from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion, Ospf from seedemu.layers.Scion import LinkType as ScLinkType # Initialize @@ -124,6 +124,7 @@ def generate(self): routing = ScionRouting() scion_isd = ScionIsd() scion = Scion() +ospf = Ospf() """ @@ -148,6 +149,11 @@ def generate(self): emu.addLayer(routing) emu.addLayer(scion_isd) emu.addLayer(scion) +emu.addLayer(ospf) + +# dump seed emulation to file before rendering +emu.dump("{self._args.output_dir}/{SEED_CONF.replace('.py', '.bin')}") + emu.render() @@ -454,6 +460,18 @@ def _create_AS(self) -> str: code = "# Ases \n" + AS_template = """\ +# AS-{as_num} +as{as_num} = base.createAutonomousSystem({as_num}) +{set_note} +scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core}) +{cert_issuer} +{set_link_properties} +as{as_num}.createControlService('cs_1').joinNetwork('net0') +{border_routers} + +""" + for As in self._topo_file["ASes"]: (as_num, @@ -466,32 +484,32 @@ def _create_AS(self) -> str: as_int_mtu, as_note) = self._parse_AS_properties(As) - code += f"\n# AS-{as_num}\n" - code += f"as{as_num} = base.createAutonomousSystem({as_num})\n" - if as_note: - code += f"as{as_num}.setNote('{as_note}')\n" - code += f"scion_isd.addIsdAs({isd_num},{as_num},is_core={is_core})\n" + set_note = f"as{as_num}.setNote('{as_note}')" if as_note else "" + if cert_issuer: - code += f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})\n" - if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored - code += (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}," - f"bandwidth={as_int_bw}," - f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") + cert_issuer = f"scion_isd.setCertIssuer(({isd_num},{as_num}),issuer={cert_issuer})" else: - code += (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}, " - f"bandwidth={as_int_bw}, " - f"packetDrop={as_int_drop})\n") + cert_issuer = "" - code += f"as{as_num}.createControlService('cs_1').joinNetwork('net0')\n" + if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored + set_link_properties = (f"as{as_num}.createNetwork('net0')" + f".setDefaultLinkProperties(" + f"latency={as_int_lat}," + f"bandwidth={as_int_bw}," + f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") + else: + set_link_properties = (f"as{as_num}.createNetwork('net0')" + f".setDefaultLinkProperties(" + f"latency={as_int_lat}, " + f"bandwidth={as_int_bw}, " + f"packetDrop={as_int_drop})\n") + + border_routers = "" # iterate through border routers for br in self._br[f"{isd_num}_{as_num}"]: br_name = next(iter(br.values())) - code += (f"as_{as_num}_{br_name} = as{as_num}" + border_routers += (f"as_{as_num}_{br_name} = as{as_num}" f".createRouter('{br_name}')" f".joinNetwork('net0')\n") @@ -504,10 +522,10 @@ def _create_AS(self) -> str: lat = br_props['geo']['latitude'] lon = br_props['geo']['longitude'] addr = br_props['geo']['address'] - code += (f"as_{as_num}_{br_name}" + border_routers += (f"as_{as_num}_{br_name}" f".setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n") if "note" in br_props: - code += f"as_{as_num}_{br_name}.setNote('{br_props['note']}')\n" + border_routers += f"as_{as_num}_{br_name}.setNote('{br_props['note']}')\n" # create crosslinks for each border router for link in self._links: @@ -525,12 +543,12 @@ def _create_AS(self) -> str: mtu = link['mtu'] # generate code if mtu: - code += (f"as_{as_num}_{br_name}" + border_routers += (f"as_{as_num}_{br_name}" f".crossConnect({b_as},'{b_br}','{a_addr}'," f"latency={latency},bandwidth={bandwidth}," f"packetDrop={packetDrop},MTU={mtu})\n") else: - code += (f"as_{as_num}_{br_name}" + border_routers += (f"as_{as_num}_{br_name}" f".crossConnect({b_as},'{b_br}','{a_addr}'," f"latency={latency},bandwidth={bandwidth}," f"packetDrop={packetDrop})\n") @@ -545,15 +563,24 @@ def _create_AS(self) -> str: packetDrop = link['drop'] mtu = link['mtu'] if mtu: - code += (f"as_{as_num}_{br_name}" + border_routers += (f"as_{as_num}_{br_name}" f".crossConnect({a_as},'{a_br}','{b_addr}'," f"latency={latency},bandwidth={bandwidth}," f"packetDrop={packetDrop},MTU={mtu})\n") else: - code += (f"as_{as_num}_{br_name}" + border_routers += (f"as_{as_num}_{br_name}" f".crossConnect({a_as},'{a_br}','{b_addr}'," f"latency={latency},bandwidth={bandwidth}," f"packetDrop={packetDrop})\n") + + code += AS_template.format(as_num=as_num, + isd_num=isd_num, + is_core=is_core, + cert_issuer=cert_issuer, + set_note=set_note, + set_link_properties=set_link_properties, + border_routers=border_routers).replace("\n\n", "\n") + return code def _create_Routing(self) -> str: From cc256cba13a7f15d71b560f333e188c0b30168e5 Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 3 Jun 2024 11:25:44 +0200 Subject: [PATCH 33/46] tried to fix linting --- tools/topology/seed.py | 66 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 9746f80f00..86972b9e79 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -492,26 +492,26 @@ def _create_AS(self) -> str: cert_issuer = "" if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored - set_link_properties = (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}," - f"bandwidth={as_int_bw}," - f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") + set_link_properties = (f"as{as_num}.createNetwork('net0')" + f".setDefaultLinkProperties(" + f"latency={as_int_lat}," + f"bandwidth={as_int_bw}," + f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") else: - set_link_properties = (f"as{as_num}.createNetwork('net0')" - f".setDefaultLinkProperties(" - f"latency={as_int_lat}, " - f"bandwidth={as_int_bw}, " - f"packetDrop={as_int_drop})\n") - + set_link_properties = (f"as{as_num}.createNetwork('net0')" + f".setDefaultLinkProperties(" + f"latency={as_int_lat}, " + f"bandwidth={as_int_bw}, " + f"packetDrop={as_int_drop})\n") + border_routers = "" # iterate through border routers for br in self._br[f"{isd_num}_{as_num}"]: br_name = next(iter(br.values())) border_routers += (f"as_{as_num}_{br_name} = as{as_num}" - f".createRouter('{br_name}')" - f".joinNetwork('net0')\n") + f".createRouter('{br_name}')" + f".joinNetwork('net0')\n") # set border router properties if f"{isd_num}_{as_num}" in self._brProperties \ @@ -523,7 +523,7 @@ def _create_AS(self) -> str: lon = br_props['geo']['longitude'] addr = br_props['geo']['address'] border_routers += (f"as_{as_num}_{br_name}" - f".setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n") + f".setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n") if "note" in br_props: border_routers += f"as_{as_num}_{br_name}.setNote('{br_props['note']}')\n" @@ -544,14 +544,14 @@ def _create_AS(self) -> str: # generate code if mtu: border_routers += (f"as_{as_num}_{br_name}" - f".crossConnect({b_as},'{b_br}','{a_addr}'," - f"latency={latency},bandwidth={bandwidth}," - f"packetDrop={packetDrop},MTU={mtu})\n") + f".crossConnect({b_as},'{b_br}','{a_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop},MTU={mtu})\n") else: border_routers += (f"as_{as_num}_{br_name}" - f".crossConnect({b_as},'{b_br}','{a_addr}'," - f"latency={latency},bandwidth={bandwidth}," - f"packetDrop={packetDrop})\n") + f".crossConnect({b_as},'{b_br}','{a_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop})\n") if link['b'][0] == isd_num and link['b'][1] == as_num: if link['b'][2] == br_name: @@ -564,23 +564,23 @@ def _create_AS(self) -> str: mtu = link['mtu'] if mtu: border_routers += (f"as_{as_num}_{br_name}" - f".crossConnect({a_as},'{a_br}','{b_addr}'," - f"latency={latency},bandwidth={bandwidth}," - f"packetDrop={packetDrop},MTU={mtu})\n") + f".crossConnect({a_as},'{a_br}','{b_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop},MTU={mtu})\n") else: border_routers += (f"as_{as_num}_{br_name}" - f".crossConnect({a_as},'{a_br}','{b_addr}'," - f"latency={latency},bandwidth={bandwidth}," - f"packetDrop={packetDrop})\n") + f".crossConnect({a_as},'{a_br}','{b_addr}'," + f"latency={latency},bandwidth={bandwidth}," + f"packetDrop={packetDrop})\n") code += AS_template.format(as_num=as_num, - isd_num=isd_num, - is_core=is_core, - cert_issuer=cert_issuer, - set_note=set_note, - set_link_properties=set_link_properties, - border_routers=border_routers).replace("\n\n", "\n") - + isd_num=isd_num, + is_core=is_core, + cert_issuer=cert_issuer, + set_note=set_note, + set_link_properties=set_link_properties, + border_routers=border_routers).replace("\n\n", "\n") + return code def _create_Routing(self) -> str: From 8e1b75caeda8e2b1f9ee254473b52854b8a16180 Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 3 Jun 2024 11:31:04 +0200 Subject: [PATCH 34/46] tried to fix linting --- tools/topology/seed.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 86972b9e79..056b72934b 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -574,11 +574,11 @@ def _create_AS(self) -> str: f"packetDrop={packetDrop})\n") code += AS_template.format(as_num=as_num, - isd_num=isd_num, - is_core=is_core, - cert_issuer=cert_issuer, - set_note=set_note, - set_link_properties=set_link_properties, + isd_num=isd_num, + is_core=is_core, + cert_issuer=cert_issuer, + set_note=set_note, + set_link_properties=set_link_properties, border_routers=border_routers).replace("\n\n", "\n") return code From e50d6bbd187e3a0e731d67a6f0d915dd6f21daee Mon Sep 17 00:00:00 2001 From: bruol Date: Mon, 3 Jun 2024 11:38:48 +0200 Subject: [PATCH 35/46] tried to fix linting --- tools/topology/seed.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 056b72934b..41d5128e9b 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -523,7 +523,8 @@ def _create_AS(self) -> str: lon = br_props['geo']['longitude'] addr = br_props['geo']['address'] border_routers += (f"as_{as_num}_{br_name}" - f".setGeo(Lat={lat}, Long={lon}, Address=\"\"\"{addr}\"\"\")\n") + f".setGeo(Lat={lat}, " + f"Long={lon}, Address=\"\"\"{addr}\"\"\")\n") if "note" in br_props: border_routers += f"as_{as_num}_{br_name}.setNote('{br_props['note']}')\n" From ddc33f29e301a403154e86c2f8dd525f63ee096c Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 19 Jul 2024 09:21:45 +0000 Subject: [PATCH 36/46] updated seed to use the new version of the internet map, which allows changing link properties dynamicially --- tools/topology/seed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 41d5128e9b..8b77bf4e85 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -158,7 +158,7 @@ def generate(self): emu.render() # Compilation -emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}), \ +emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}, internetMapClientImage="bruol0/seedemu-client"), \ './{self._args.output_dir}/seed-compiled') """ # write seed file From 5a46a0126151e508e808af904ca0bdbcf16260df Mon Sep 17 00:00:00 2001 From: bruol Date: Fri, 19 Jul 2024 12:21:39 +0000 Subject: [PATCH 37/46] fixed linter error --- tools/topology/seed.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 8b77bf4e85..839a1814c9 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -158,7 +158,8 @@ def generate(self): emu.render() # Compilation -emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}, internetMapClientImage="bruol0/seedemu-client"), \ +emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}, \ +internetMapClientImage="bruol0/seedemu-client"), \ './{self._args.output_dir}/seed-compiled') """ # write seed file From ff4c060e716b5d8b2ca2cf0c5c5c03c620535926 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 12:22:00 +0000 Subject: [PATCH 38/46] made as internal networks use specified parent net --- tools/topology/seed.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 839a1814c9..fbdc252c98 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -45,6 +45,16 @@ def __init__(self, args, topo_dicts, # class to generate IP addresses for cross connect links +class ASNetworkAssigner: + def __init__(self, parentNet): + assert "/16" in parentNet, "Parent network must be a /16 network" + self.parentNet = ".".join(parentNet.split(".")[0:2]) + + def get_net_by_as(self, asn): + if asn == 0: + raise Exception("AS number 0 is invalid") + return f"{self.parentNet}.{asn}.0/24" + class CrossConnectNetAssigner: def __init__(self, parentNet): self.subnet_iter = IPv4Network(parentNet).subnets(new_prefix=29) @@ -442,6 +452,8 @@ def _generate_addresses(self): """ self._xc_nets = CrossConnectNetAssigner(self._parentNetwork) + self.as_nets = ASNetworkAssigner(self._parentNetwork) + for i in range(0, len(self._links)): link = self._links[i] @@ -493,13 +505,13 @@ def _create_AS(self) -> str: cert_issuer = "" if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored - set_link_properties = (f"as{as_num}.createNetwork('net0')" + set_link_properties = (f"as{as_num}.createNetwork('net0', prefix=\"{self.as_nets.get_net_by_as(as_num)}\")" f".setDefaultLinkProperties(" f"latency={as_int_lat}," f"bandwidth={as_int_bw}," f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") else: - set_link_properties = (f"as{as_num}.createNetwork('net0')" + set_link_properties = (f"as{as_num}.createNetwork('net0', prefix=\"{self.as_nets.get_net_by_as(as_num)}\")" f".setDefaultLinkProperties(" f"latency={as_int_lat}, " f"bandwidth={as_int_bw}, " From 212ee114576d93d5fbc0c622591bc0de6dd37a10 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 12:40:23 +0000 Subject: [PATCH 39/46] adapted scion.sh to support flags for setting cross connect and AS internal network prefixes --- tools/topogen.py | 4 ++++ tools/topology/seed.py | 17 ++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tools/topogen.py b/tools/topogen.py index fe04b675b7..e3059fc536 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -38,6 +38,10 @@ def add_arguments(parser): help='Create a docker compose configuration') parser.add_argument('-n', '--network', help='Network to create subnets in (E.g. "127.0.0.0/8")') + parser.add_argument("-xcn", "--xconnect-network", + help='/16 Network to create seed cross-connects subnets in (E.g. "10.3.0.0/16")') + parser.add_argument('-asn', "--as-network", + help='/16 Network to create seed AS subnets in (E.g. "10.4.0.0/16")') parser.add_argument('-o', '--output-dir', default=GEN_PATH, help='Output directory') parser.add_argument('--random-ifids', action='store_true', diff --git a/tools/topology/seed.py b/tools/topology/seed.py index fbdc252c98..1c0ca4c967 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -38,6 +38,8 @@ def __init__(self, args, topo_dicts, """ super().__init__(args, topo_dicts) self.networks = networks + print("SeedGenArgs\n") + print(args) # copyright @@ -51,8 +53,6 @@ def __init__(self, parentNet): self.parentNet = ".".join(parentNet.split(".")[0:2]) def get_net_by_as(self, asn): - if asn == 0: - raise Exception("AS number 0 is invalid") return f"{self.parentNet}.{asn}.0/24" class CrossConnectNetAssigner: @@ -82,6 +82,7 @@ class SeedGenerator(SeedGenArgs): _SeedCompiler: str = "Docker" _skipIPv6Check: bool = False _parentNetwork: str = "10.3.0.0/16" + _as_network: str = "10.4.0.0/16" # dict containing mapping from ISD_AS to list of border router properties _brProperties: Dict[str, Dict[str, Dict]] @@ -108,8 +109,11 @@ def _parseFeatures(self): self._SeedCompiler = "Graphviz" if "SeedSkipIPv6Check" in self._args.features: self._skipIPv6Check = True - if self._args.network: - self._parentNetwork = self._args.network + if self._args.xconnect_network: + self._parentNetwork = self._args.xconnect_network + if self._args.as_network: + self._as_network = self._args.as_network + def generate(self): """ @@ -121,8 +125,7 @@ def generate(self): self._check_IPv6() # write header of seed file - self._out_file = """ - + self._out_file = """\ from seedemu.compiler import Docker from seedemu.core import Emulator from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion, Ospf @@ -452,7 +455,7 @@ def _generate_addresses(self): """ self._xc_nets = CrossConnectNetAssigner(self._parentNetwork) - self.as_nets = ASNetworkAssigner(self._parentNetwork) + self.as_nets = ASNetworkAssigner(self._as_network) for i in range(0, len(self._links)): link = self._links[i] From 9bc79db39bad0ad1028fed6368524c85a4f43671 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 12:50:49 +0000 Subject: [PATCH 40/46] fixed linter errors --- tools/topology/seed.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 1c0ca4c967..8eda9e5e17 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -51,10 +51,11 @@ class ASNetworkAssigner: def __init__(self, parentNet): assert "/16" in parentNet, "Parent network must be a /16 network" self.parentNet = ".".join(parentNet.split(".")[0:2]) - + def get_net_by_as(self, asn): return f"{self.parentNet}.{asn}.0/24" + class CrossConnectNetAssigner: def __init__(self, parentNet): self.subnet_iter = IPv4Network(parentNet).subnets(new_prefix=29) @@ -113,7 +114,6 @@ def _parseFeatures(self): self._parentNetwork = self._args.xconnect_network if self._args.as_network: self._as_network = self._args.as_network - def generate(self): """ @@ -508,13 +508,15 @@ def _create_AS(self) -> str: cert_issuer = "" if as_int_mtu: # default value 0 for latency, bandwidth, packetDrop will be ignored - set_link_properties = (f"as{as_num}.createNetwork('net0', prefix=\"{self.as_nets.get_net_by_as(as_num)}\")" + set_link_properties = (f"as{as_num}.createNetwork('net0', " + f"prefix=\"{self.as_nets.get_net_by_as(as_num)}\")" f".setDefaultLinkProperties(" f"latency={as_int_lat}," f"bandwidth={as_int_bw}," f"packetDrop={as_int_drop}).setMtu({as_int_mtu})\n") else: - set_link_properties = (f"as{as_num}.createNetwork('net0', prefix=\"{self.as_nets.get_net_by_as(as_num)}\")" + set_link_properties = (f"as{as_num}.createNetwork('net0', " + f"prefix=\"{self.as_nets.get_net_by_as(as_num)}\")" f".setDefaultLinkProperties(" f"latency={as_int_lat}, " f"bandwidth={as_int_bw}, " From 912fe703e80f863181d663062806e80cebcac5b2 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 14:24:20 +0000 Subject: [PATCH 41/46] fixed bug with graphviz compiler --- tools/topology/seed.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 8eda9e5e17..f12307838a 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -126,7 +126,7 @@ def generate(self): # write header of seed file self._out_file = """\ -from seedemu.compiler import Docker +from seedemu.compiler import Docker, Graphviz from seedemu.core import Emulator from seedemu.layers import ScionBase, ScionRouting, ScionIsd, Scion, Ospf from seedemu.layers.Scion import LinkType as ScLinkType @@ -171,8 +171,8 @@ def generate(self): emu.render() # Compilation -emu.compile({self._SeedCompiler}(internetMapEnabled={self._internetMapEnabled}, \ -internetMapClientImage="bruol0/seedemu-client"), \ +emu.compile({self._SeedCompiler}{"(internetMapEnabled={self._internetMapEnabled}, \ +internetMapClientImage=\"bruol0/seedemu-client\")" if self._SeedCompiler == "Docker" else "()"}, \ './{self._args.output_dir}/seed-compiled') """ # write seed file From 8b30af6a216818ef49bb13118b7aedd8ce5b0e17 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 14:24:46 +0000 Subject: [PATCH 42/46] added section on how to generate seed emulation to documentation --- doc/dev/run.rst | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/doc/dev/run.rst b/doc/dev/run.rst index bb7b3f605a..72b61ceb06 100644 --- a/doc/dev/run.rst +++ b/doc/dev/run.rst @@ -181,6 +181,11 @@ The basic usage is ``./scion.sh ``. The main subcommands a .. option:: -h, --help Display help text, list all options + + .. option:: -s, --seed + + Generate a seed emulation from the topology file. + For more Information check out the :ref:`generating-seed-emulation` section. .. option:: run, start @@ -209,6 +214,62 @@ The basic usage is ``./scion.sh ``. The main subcommands a Describe all available subcommands +.. _generating-seed-emulation: + +generating seed emulation +========================= + +To generate a seed emulation from a topology file, you need this version of the +`seed-emulator `_ installed. + +The basic usage is ``./scion.sh topology -s -c /path/to/topology/file``. + +This will generate the following files in the gen directory: + +1. A seed emulation file called ``scion-seed.py``. This file contains the seed emulation + +2. A seed emulation dump file called ``scion-seed.bin``. + This is a binary dump of the seed emulation. + You will need this for example if you want to use the + `seed traffic generator `_. + +3. A folder called ``seed-compiled``. This folder contains the compiled seed emulation. + This folder is what you get when you run the ``scion-seed.py`` file. + Executing ``docker compose up --build`` in this folder will start the seed emulation. + +.. Note:: + seed currently only supports IPv4 therefore the -s flag is not available if the + topology file contains IPv6 underlay networks. + +.. option:: -xcn, --xconnect-network + + This flag allows you tho specify the subnet that the + seed cross connect networks will be created in. + The default is `10.3.0.0/16`. + +.. option:: -asn, --as-network + + This flag allows you tho specify the subnet that the + seed AS internal networks will be created in. + The default is `10.4.0.0/16`. + +.. option:: --features + + .. option:: SeedInternetMapDisable + + This will disable the internet map feature of the seed emulation. + + .. option:: SeedCompilerGraphviz + + This will enable the graphviz compiler of the seed compiler. + Instead of a docker compose file the ``gen/seed-compiled`` folder will contain a + graphviz file which can be used to visualize the seed emulation. + + .. option:: SeedSkipIPv6Check + + This will skip the IPv6 check and treat topology files with IPv6 underlay networks + as if the underlay networks were IPv4. + end2end_integration =================== @@ -222,3 +283,4 @@ The basic usage is ``./end2end_integration ``. Assume the SCION services are dockerized. Must be consistent with the last invocation of ``scion.sh topology``. + From f2e861eca0779ae403fdcc3bee09695f226f6716 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 14:34:54 +0000 Subject: [PATCH 43/46] fixed linting --- doc/dev/run.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/dev/run.rst b/doc/dev/run.rst index 72b61ceb06..9501106ab6 100644 --- a/doc/dev/run.rst +++ b/doc/dev/run.rst @@ -181,10 +181,10 @@ The basic usage is ``./scion.sh ``. The main subcommands a .. option:: -h, --help Display help text, list all options - + .. option:: -s, --seed - Generate a seed emulation from the topology file. + Generate a seed emulation from the topology file. For more Information check out the :ref:`generating-seed-emulation` section. .. option:: run, start @@ -219,7 +219,7 @@ The basic usage is ``./scion.sh ``. The main subcommands a generating seed emulation ========================= -To generate a seed emulation from a topology file, you need this version of the +To generate a seed emulation from a topology file, you need this version of the `seed-emulator `_ installed. The basic usage is ``./scion.sh topology -s -c /path/to/topology/file``. @@ -228,9 +228,9 @@ This will generate the following files in the gen directory: 1. A seed emulation file called ``scion-seed.py``. This file contains the seed emulation -2. A seed emulation dump file called ``scion-seed.bin``. - This is a binary dump of the seed emulation. - You will need this for example if you want to use the +2. A seed emulation dump file called ``scion-seed.bin``. + This is a binary dump of the seed emulation. + You will need this for example if you want to use the `seed traffic generator `_. 3. A folder called ``seed-compiled``. This folder contains the compiled seed emulation. @@ -238,19 +238,19 @@ This will generate the following files in the gen directory: Executing ``docker compose up --build`` in this folder will start the seed emulation. .. Note:: - seed currently only supports IPv4 therefore the -s flag is not available if the + seed currently only supports IPv4 therefore the -s flag is not available if the topology file contains IPv6 underlay networks. .. option:: -xcn, --xconnect-network - This flag allows you tho specify the subnet that the - seed cross connect networks will be created in. + This flag allows you tho specify the subnet that the + seed cross connect networks will be created in. The default is `10.3.0.0/16`. .. option:: -asn, --as-network - This flag allows you tho specify the subnet that the - seed AS internal networks will be created in. + This flag allows you tho specify the subnet that the + seed AS internal networks will be created in. The default is `10.4.0.0/16`. .. option:: --features @@ -262,9 +262,9 @@ This will generate the following files in the gen directory: .. option:: SeedCompilerGraphviz This will enable the graphviz compiler of the seed compiler. - Instead of a docker compose file the ``gen/seed-compiled`` folder will contain a + Instead of a docker compose file the ``gen/seed-compiled`` folder will contain a graphviz file which can be used to visualize the seed emulation. - + .. option:: SeedSkipIPv6Check This will skip the IPv6 check and treat topology files with IPv6 underlay networks From a8a0bba3a22166e25d846aade619f7d16325e49f Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 14:42:35 +0000 Subject: [PATCH 44/46] tried again to fix linting --- tools/topology/seed.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index f12307838a..4cf741d286 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -171,8 +171,8 @@ def generate(self): emu.render() # Compilation -emu.compile({self._SeedCompiler}{"(internetMapEnabled={self._internetMapEnabled}, \ -internetMapClientImage=\"bruol0/seedemu-client\")" if self._SeedCompiler == "Docker" else "()"}, \ +emu.compile({self._SeedCompiler}{'(internetMapEnabled={self._internetMapEnabled}, \ +internetMapClientImage="bruol0/seedemu-client")' if self._SeedCompiler == "Docker" else "()"}, \ './{self._args.output_dir}/seed-compiled') """ # write seed file From 5028019ba2f2e5ff9023d2a83cb0d7759f8e3348 Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 14:49:53 +0000 Subject: [PATCH 45/46] tried again --- tools/topology/seed.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index 4cf741d286..fda6ddd6aa 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -171,8 +171,9 @@ def generate(self): emu.render() # Compilation -emu.compile({self._SeedCompiler}{'(internetMapEnabled={self._internetMapEnabled}, \ -internetMapClientImage="bruol0/seedemu-client")' if self._SeedCompiler == "Docker" else "()"}, \ +emu.compile({self._SeedCompiler}{f'(internetMapEnabled={self._internetMapEnabled},' + f'internetMapClientImage="bruol0/seedemu-client")' + if self._SeedCompiler == "Docker" else "()"}, \ './{self._args.output_dir}/seed-compiled') """ # write seed file From 7c09fd7f096b0e06734088a7030cf27c062e4f1a Mon Sep 17 00:00:00 2001 From: bruol Date: Wed, 14 Aug 2024 14:54:04 +0000 Subject: [PATCH 46/46] tried again --- tools/topology/seed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/topology/seed.py b/tools/topology/seed.py index fda6ddd6aa..b5c1664937 100644 --- a/tools/topology/seed.py +++ b/tools/topology/seed.py @@ -172,7 +172,7 @@ def generate(self): # Compilation emu.compile({self._SeedCompiler}{f'(internetMapEnabled={self._internetMapEnabled},' - f'internetMapClientImage="bruol0/seedemu-client")' + f'internetMapClientImage="bruol0/seedemu-client")' if self._SeedCompiler == "Docker" else "()"}, \ './{self._args.output_dir}/seed-compiled') """