From 303821a5e97df5919334c0089f9067c5d6c2bfc6 Mon Sep 17 00:00:00 2001 From: Stanislav Kosorin Date: Wed, 7 Aug 2024 14:23:17 +0000 Subject: [PATCH 1/4] Use a json config as argument for controller Previously, the p4info, bmv2_json and multi_switch arguments were passed to the controller as command line arguments and the switch configuration was hardcoded. This commit makes it possible to configure any number of switches in the configuration file, and also to customize the parameters of individual switches. --- .gitignore | 1 - controller/controller.py | 132 +++++++----------- controller/switch_controller.py | 10 +- examples/host_containers/Makefile | 7 +- .../host_containers/config}/s1-runtime.json | 0 .../host_containers/config}/s2-runtime.json | 0 .../host_containers/config}/s3-runtime.json | 0 .../host_containers/config}/s4-runtime.json | 0 examples/host_containers/config/switches.json | 42 ++++++ examples/process_migration/Makefile | 7 +- .../process_migration/config/s1-runtime.json | 106 ++++++++++++++ .../process_migration/config/s2-runtime.json | 85 +++++++++++ .../process_migration/config/s3-runtime.json | 85 +++++++++++ .../process_migration/config/s4-runtime.json | 85 +++++++++++ .../process_migration/config/switches.json | 42 ++++++ examples/switch_container/Makefile | 7 +- .../switch_container/config/s1-runtime.json | 100 +++++++++++++ .../switch_container/config/switches.json | 12 ++ utils/Makefile | 7 - 19 files changed, 631 insertions(+), 97 deletions(-) rename {load_balancer => examples/host_containers/config}/s1-runtime.json (100%) rename {load_balancer => examples/host_containers/config}/s2-runtime.json (100%) rename {load_balancer => examples/host_containers/config}/s3-runtime.json (100%) rename {load_balancer => examples/host_containers/config}/s4-runtime.json (100%) create mode 100644 examples/host_containers/config/switches.json create mode 100644 examples/process_migration/config/s1-runtime.json create mode 100644 examples/process_migration/config/s2-runtime.json create mode 100644 examples/process_migration/config/s3-runtime.json create mode 100644 examples/process_migration/config/s4-runtime.json create mode 100644 examples/process_migration/config/switches.json create mode 100644 examples/switch_container/config/s1-runtime.json create mode 100644 examples/switch_container/config/switches.json diff --git a/.gitignore b/.gitignore index 5661c64..9f5b34c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ *~ # Compiled JSON -*.json !*p4app.json !topology.json !*-runtime.json diff --git a/controller/controller.py b/controller/controller.py index 0878776..26a9077 100755 --- a/controller/controller.py +++ b/controller/controller.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import argparse +import json import os import sys @@ -13,69 +14,62 @@ global nodeManager -def main(p4info_file_path, bmv2_file_path, multi_switch=False): +def main(config_file_path): try: - if multi_switch: - # Program switches - # s2 - SwitchController( - p4info_file_path=p4info_file_path, - bmv2_file_path=bmv2_file_path, - sw_name="s2", - sw_addr="127.0.0.1:50052", - sw_id=1, - proto_dump_file=( - "../load_balancer/logs/s2-p4runtime-requests.txt" - ), - initial_table_rules_file="../load_balancer/s2-runtime.json", + with open(config_file_path, "r") as config_file: + switch_configs = json.load(config_file) + + switch_controllers = [] + master_config = None + + for config in switch_configs: + # Master needs to be initialized last, + # otherwise performing master arbitration update will fail + if config.get("master", False): + if master_config is not None: + raise Exception( + "Multiple master switches specified " + "in the configuration file." + ) + master_config = config + continue + + switch_controller = SwitchController( + p4info_file_path=config["p4info_file_path"], + bmv2_file_path=config["bmv2_file_path"], + sw_name=config["name"], + sw_addr=config["addr"], + sw_id=config["id"], + proto_dump_file=config["proto_dump_file"], + initial_table_rules_file=config["runtime_file"], ) + switch_controllers.append(switch_controller) - # s3 - SwitchController( - p4info_file_path=p4info_file_path, - bmv2_file_path=bmv2_file_path, - sw_name="s3", - sw_addr="127.0.0.1:50053", - sw_id=2, - proto_dump_file=( - "../load_balancer/logs/s3-p4runtime-requests.txt" - ), - initial_table_rules_file="../load_balancer/s3-runtime.json", + if master_config is None: + raise Exception( + "No master switch specified in the configuration file." ) - # s4 (no path to this switch from s1) - SwitchController( - p4info_file_path=p4info_file_path, - bmv2_file_path=bmv2_file_path, - sw_name="s4", - sw_addr="127.0.0.1:50054", - sw_id=3, - proto_dump_file=( - "../load_balancer/logs/s4-p4runtime-requests.txt" - ), - initial_table_rules_file="../load_balancer/s4-runtime.json", - ) - - # s1 - # s1 needs to be last so that this controller is set - # as master (otherwise write operations won't work) - switch_controller = SwitchController( - p4info_file_path=p4info_file_path, - bmv2_file_path=bmv2_file_path, - sw_name="s1", - sw_addr="0.0.0.0:50051", - sw_id=0, - proto_dump_file="../load_balancer/logs/s1-p4runtime-requests.txt", - initial_table_rules_file="../load_balancer/s1-runtime.json", + master_controller = SwitchController( + p4info_file_path=master_config["p4info_file_path"], + bmv2_file_path=master_config["bmv2_file_path"], + sw_name=master_config["name"], + sw_addr=master_config["addr"], + sw_id=master_config["id"], + proto_dump_file=master_config["proto_dump_file"], + initial_table_rules_file=master_config["runtime_file"], ) global nodeManager - nodeManager = NodeManager(switch_controller) + nodeManager = NodeManager(master_controller) except KeyboardInterrupt: print("Shutting down.") except grpc.RpcError as e: printGrpcError(e) exit(1) + except Exception as e: + print(f"Error: {e}") + exit(1) app.run(port=5000) @@ -121,42 +115,16 @@ def update_node(): if __name__ == "__main__": parser = argparse.ArgumentParser(description="P4Runtime Controller") parser.add_argument( - "--p4info", - help="p4info proto in text format from p4c", + "--config", + help="JSON configuration file for switches", type=str, action="store", - required=False, - default="../load_balancer/build/load_balance.p4.p4info.txt", - ) - parser.add_argument( - "--bmv2-json", - help="BMv2 JSON file from p4c", - type=str, - action="store", - required=False, - default="../load_balancer/build/load_balance.json", - ) - parser.add_argument( - "--multi_switch", - help="BMv2 JSON file from p4c", - type=bool, - action="store", - required=False, - default=False, + required=True, ) args = parser.parse_args() - if not os.path.exists(args.p4info): - parser.print_help() - print( - "\np4info file not found: %s\nHave you run 'make'?" % args.p4info - ) - parser.exit(1) - if not os.path.exists(args.bmv2_json): + if not os.path.exists(args.config): parser.print_help() - print( - "\nBMv2 JSON file not found: %s\nHave you run 'make'?" - % args.bmv2_json - ) + print(f"\nConfiguration file not found: {args.config}") parser.exit(1) - main(args.p4info, args.bmv2_json, args.multi_switch) + main(args.config) diff --git a/controller/switch_controller.py b/controller/switch_controller.py index 9a0f538..fe3e742 100644 --- a/controller/switch_controller.py +++ b/controller/switch_controller.py @@ -4,8 +4,8 @@ import p4runtime_lib.bmv2 import p4runtime_lib.helper -from p4runtime_lib.switch import ShutdownAllSwitchConnections from p4runtime_lib.simple_controller import program_from_file +from p4runtime_lib.switch import ShutdownAllSwitchConnections class SwitchController(object): @@ -19,6 +19,14 @@ def __init__( proto_dump_file, initial_table_rules_file=None, ): + self.p4info_file_path = p4info_file_path + self.bmv2_file_path = bmv2_file_path + self.sw_name = sw_name + self.sw_addr = sw_addr + self.sw_id = sw_id + self.proto_dump_file = proto_dump_file + self.initial_table_rules_file = initial_table_rules_file + self.p4info_helper = p4runtime_lib.helper.P4InfoHelper( p4info_file_path ) diff --git a/examples/host_containers/Makefile b/examples/host_containers/Makefile index 2e12ddb..64118a9 100644 --- a/examples/host_containers/Makefile +++ b/examples/host_containers/Makefile @@ -1,12 +1,15 @@ include ../../utils/Makefile -all: compile build control_multi_switch +all: compile build controller terminals: h1 h2 h3 h4 build: clean ./build.sh +controller: + sleep 2 && ../../controller/controller.py --config config/switches.json + clean: ./clean.sh @@ -29,4 +32,4 @@ h3: h4: xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h4" -hold -e "sudo podman logs -f h4" & -.PHONY: all terminals build clean migrate h1 h2 h3 h4 +.PHONY: all terminals build controller clean migrate h1 h2 h3 h4 diff --git a/load_balancer/s1-runtime.json b/examples/host_containers/config/s1-runtime.json similarity index 100% rename from load_balancer/s1-runtime.json rename to examples/host_containers/config/s1-runtime.json diff --git a/load_balancer/s2-runtime.json b/examples/host_containers/config/s2-runtime.json similarity index 100% rename from load_balancer/s2-runtime.json rename to examples/host_containers/config/s2-runtime.json diff --git a/load_balancer/s3-runtime.json b/examples/host_containers/config/s3-runtime.json similarity index 100% rename from load_balancer/s3-runtime.json rename to examples/host_containers/config/s3-runtime.json diff --git a/load_balancer/s4-runtime.json b/examples/host_containers/config/s4-runtime.json similarity index 100% rename from load_balancer/s4-runtime.json rename to examples/host_containers/config/s4-runtime.json diff --git a/examples/host_containers/config/switches.json b/examples/host_containers/config/switches.json new file mode 100644 index 0000000..dd78560 --- /dev/null +++ b/examples/host_containers/config/switches.json @@ -0,0 +1,42 @@ +[ + { + "id": 0, + "name": "s1", + "addr": "0.0.0.0:50051", + "proto_dump_file": "../../load_balancer/logs/s1-p4runtime-requests.txt", + "runtime_file": "./config/s1-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": true + }, + { + "id": 1, + "name": "s2", + "addr": "127.0.0.1:50052", + "proto_dump_file": "../../load_balancer/logs/s2-p4runtime-requests.txt", + "runtime_file": "./config/s2-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": false + }, + { + "id": 2, + "name": "s3", + "addr": "127.0.0.1:50053", + "proto_dump_file": "../../load_balancer/logs/s3-p4runtime-requests.txt", + "runtime_file": "./config/s3-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": false + }, + { + "id": 3, + "name": "s4", + "addr": "127.0.0.1:50054", + "proto_dump_file": "../../load_balancer/logs/s4-p4runtime-requests.txt", + "runtime_file": "./config/s4-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": false + } +] diff --git a/examples/process_migration/Makefile b/examples/process_migration/Makefile index cf76571..581f69f 100644 --- a/examples/process_migration/Makefile +++ b/examples/process_migration/Makefile @@ -1,13 +1,16 @@ include ../../utils/Makefile SHELL := /bin/bash -all: compile build control_multi_switch +all: compile build controller terminals: h1 h2 h3 h4 build: clean ./build.sh +controller: + sleep 2 && ../../controller/controller.py --config config/switches.json + clean: ./clean.sh @@ -30,4 +33,4 @@ h3: h4: xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h4" -hold -e "sudo ip netns exec h4 /bin/bash" & -.PHONY: all terminals build clean migrate h1 h2 h3 h4 +.PHONY: all terminals build controller clean migrate h1 h2 h3 h4 diff --git a/examples/process_migration/config/s1-runtime.json b/examples/process_migration/config/s1-runtime.json new file mode 100644 index 0000000..6fdf42e --- /dev/null +++ b/examples/process_migration/config/s1-runtime.json @@ -0,0 +1,106 @@ +{ + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.1.1", + 32 + ] + }, + "action_name": "MyIngress.set_rewrite_src", + "action_params": { + "new_src": "10.0.1.10" + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.1.10", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:02:02", + "nhop_ipv4": "10.0.2.2", + "port": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 2 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:03:03", + "nhop_ipv4": "10.0.3.3", + "port": 3 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:02:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 3 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:03:00" + } + } + ] +} \ No newline at end of file diff --git a/examples/process_migration/config/s2-runtime.json b/examples/process_migration/config/s2-runtime.json new file mode 100644 index 0000000..80e328d --- /dev/null +++ b/examples/process_migration/config/s2-runtime.json @@ -0,0 +1,85 @@ +{ + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.2.2", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 0, + "ecmp_count": 1 + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.1.1", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:02:02", + "nhop_ipv4": "10.0.2.2", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 2 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:02:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:02:02:00" + } + } + ] +} \ No newline at end of file diff --git a/examples/process_migration/config/s3-runtime.json b/examples/process_migration/config/s3-runtime.json new file mode 100644 index 0000000..703ede5 --- /dev/null +++ b/examples/process_migration/config/s3-runtime.json @@ -0,0 +1,85 @@ +{ + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.3.3", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 0, + "ecmp_count": 1 + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.1.1", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:03:03", + "nhop_ipv4": "10.0.3.3", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 2 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:03:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:03:02:00" + } + } + ] +} \ No newline at end of file diff --git a/examples/process_migration/config/s4-runtime.json b/examples/process_migration/config/s4-runtime.json new file mode 100644 index 0000000..a165b6a --- /dev/null +++ b/examples/process_migration/config/s4-runtime.json @@ -0,0 +1,85 @@ +{ + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.4.4", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 0, + "ecmp_count": 1 + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": [ + "10.0.1.1", + 32 + ] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:04:04", + "nhop_ipv4": "10.0.4.4", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 2 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:04:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:04:02:00" + } + } + ] +} \ No newline at end of file diff --git a/examples/process_migration/config/switches.json b/examples/process_migration/config/switches.json new file mode 100644 index 0000000..dd78560 --- /dev/null +++ b/examples/process_migration/config/switches.json @@ -0,0 +1,42 @@ +[ + { + "id": 0, + "name": "s1", + "addr": "0.0.0.0:50051", + "proto_dump_file": "../../load_balancer/logs/s1-p4runtime-requests.txt", + "runtime_file": "./config/s1-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": true + }, + { + "id": 1, + "name": "s2", + "addr": "127.0.0.1:50052", + "proto_dump_file": "../../load_balancer/logs/s2-p4runtime-requests.txt", + "runtime_file": "./config/s2-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": false + }, + { + "id": 2, + "name": "s3", + "addr": "127.0.0.1:50053", + "proto_dump_file": "../../load_balancer/logs/s3-p4runtime-requests.txt", + "runtime_file": "./config/s3-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": false + }, + { + "id": 3, + "name": "s4", + "addr": "127.0.0.1:50054", + "proto_dump_file": "../../load_balancer/logs/s4-p4runtime-requests.txt", + "runtime_file": "./config/s4-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": false + } +] diff --git a/examples/switch_container/Makefile b/examples/switch_container/Makefile index 36bf881..64118a9 100644 --- a/examples/switch_container/Makefile +++ b/examples/switch_container/Makefile @@ -1,12 +1,15 @@ include ../../utils/Makefile -all: compile build control +all: compile build controller terminals: h1 h2 h3 h4 build: clean ./build.sh +controller: + sleep 2 && ../../controller/controller.py --config config/switches.json + clean: ./clean.sh @@ -29,4 +32,4 @@ h3: h4: xterm -xrm 'XTerm.vt100.allowTitleOps: false' -T "h4" -hold -e "sudo podman logs -f h4" & -.PHONY: all terminals build clean migrate h1 h2 h3 h4 +.PHONY: all terminals build controller clean migrate h1 h2 h3 h4 diff --git a/examples/switch_container/config/s1-runtime.json b/examples/switch_container/config/s1-runtime.json new file mode 100644 index 0000000..733810a --- /dev/null +++ b/examples/switch_container/config/s1-runtime.json @@ -0,0 +1,100 @@ +{ + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] + }, + "action_name": "MyIngress.set_rewrite_src", + "action_params": { + "new_src": "10.0.1.10" + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": ["10.0.1.10", 32] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:02:02", + "nhop_ipv4": "10.0.2.2", + "port": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 2 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:03:03", + "nhop_ipv4": "10.0.3.3", + "port": 3 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:02:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 3 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:03:00" + } + } + ] +} diff --git a/examples/switch_container/config/switches.json b/examples/switch_container/config/switches.json new file mode 100644 index 0000000..5b3d72a --- /dev/null +++ b/examples/switch_container/config/switches.json @@ -0,0 +1,12 @@ +[ + { + "id": 0, + "name": "s1", + "addr": "0.0.0.0:50051", + "proto_dump_file": "../../load_balancer/logs/s1-p4runtime-requests.txt", + "runtime_file": "config/s1-runtime.json", + "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", + "bmv2_file_path": "../../load_balancer/build/load_balance.json", + "master": true + } +] diff --git a/utils/Makefile b/utils/Makefile index 4790004..52dfad0 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -1,4 +1,3 @@ -CONTROLLER_DIR = ../../controller LOAD_BALANCER_DIR = ../../load_balancer TCP_DIR = ../../tcp @@ -7,12 +6,6 @@ all: compile: make -C $(LOAD_BALANCER_DIR) -control_multi_switch: - cd $(CONTROLLER_DIR) && sleep 2 && ./controller.py --multi_switch=True - -control: - cd $(CONTROLLER_DIR) && sleep 2 && ./controller.py - images: make -C $(TCP_DIR) From 698a5283483145eab4649b2ddcd6a5d2d510f580 Mon Sep 17 00:00:00 2001 From: Stanislav Kosorin Date: Wed, 7 Aug 2024 14:28:14 +0000 Subject: [PATCH 2/4] Format all json runtime files --- .../host_containers/config/s1-runtime.json | 204 +++++++++--------- .../host_containers/config/s2-runtime.json | 12 +- .../host_containers/config/s3-runtime.json | 12 +- .../host_containers/config/s4-runtime.json | 12 +- .../process_migration/config/s1-runtime.json | 204 +++++++++--------- .../process_migration/config/s2-runtime.json | 12 +- .../process_migration/config/s3-runtime.json | 12 +- .../process_migration/config/s4-runtime.json | 12 +- 8 files changed, 216 insertions(+), 264 deletions(-) diff --git a/examples/host_containers/config/s1-runtime.json b/examples/host_containers/config/s1-runtime.json index 6fdf42e..733810a 100644 --- a/examples/host_containers/config/s1-runtime.json +++ b/examples/host_containers/config/s1-runtime.json @@ -1,106 +1,100 @@ { - "target": "bmv2", - "p4info": "build/load_balance.p4.p4info.txt", - "bmv2_json": "build/load_balance.json", - "table_entries": [ - { - "table": "MyIngress.ecmp_group", - "default_action": true, - "action_name": "MyIngress.drop", - "action_params": {} - }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] - }, - "action_name": "MyIngress.set_rewrite_src", - "action_params": { - "new_src": "10.0.1.10" - } - }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.10", - 32 - ] - }, - "action_name": "MyIngress.set_ecmp_select", - "action_params": { - "ecmp_base": 1, - "ecmp_count": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 0 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:01:01", - "nhop_ipv4": "10.0.1.1", - "port": 1 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 1 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:02:02", - "nhop_ipv4": "10.0.2.2", - "port": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 2 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:03:03", - "nhop_ipv4": "10.0.3.3", - "port": 3 - } - }, - { - "table": "MyEgress.send_frame", - "match": { - "standard_metadata.egress_port": 1 - }, - "action_name": "MyEgress.rewrite_mac", - "action_params": { - "smac": "00:00:00:01:01:00" - } - }, - { - "table": "MyEgress.send_frame", - "match": { - "standard_metadata.egress_port": 2 - }, - "action_name": "MyEgress.rewrite_mac", - "action_params": { - "smac": "00:00:00:01:02:00" - } - }, - { - "table": "MyEgress.send_frame", - "match": { - "standard_metadata.egress_port": 3 - }, - "action_name": "MyEgress.rewrite_mac", - "action_params": { - "smac": "00:00:00:01:03:00" - } - } - ] -} \ No newline at end of file + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] + }, + "action_name": "MyIngress.set_rewrite_src", + "action_params": { + "new_src": "10.0.1.10" + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": ["10.0.1.10", 32] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:02:02", + "nhop_ipv4": "10.0.2.2", + "port": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 2 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:03:03", + "nhop_ipv4": "10.0.3.3", + "port": 3 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:02:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 3 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:03:00" + } + } + ] +} diff --git a/examples/host_containers/config/s2-runtime.json b/examples/host_containers/config/s2-runtime.json index 80e328d..12c2b4e 100644 --- a/examples/host_containers/config/s2-runtime.json +++ b/examples/host_containers/config/s2-runtime.json @@ -12,10 +12,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.2.2", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.2.2", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -26,10 +23,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -82,4 +76,4 @@ } } ] -} \ No newline at end of file +} diff --git a/examples/host_containers/config/s3-runtime.json b/examples/host_containers/config/s3-runtime.json index 703ede5..e3cd0b4 100644 --- a/examples/host_containers/config/s3-runtime.json +++ b/examples/host_containers/config/s3-runtime.json @@ -12,10 +12,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.3.3", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.3.3", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -26,10 +23,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -82,4 +76,4 @@ } } ] -} \ No newline at end of file +} diff --git a/examples/host_containers/config/s4-runtime.json b/examples/host_containers/config/s4-runtime.json index a165b6a..8986054 100644 --- a/examples/host_containers/config/s4-runtime.json +++ b/examples/host_containers/config/s4-runtime.json @@ -12,10 +12,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.4.4", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.4.4", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -26,10 +23,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -82,4 +76,4 @@ } } ] -} \ No newline at end of file +} diff --git a/examples/process_migration/config/s1-runtime.json b/examples/process_migration/config/s1-runtime.json index 6fdf42e..733810a 100644 --- a/examples/process_migration/config/s1-runtime.json +++ b/examples/process_migration/config/s1-runtime.json @@ -1,106 +1,100 @@ { - "target": "bmv2", - "p4info": "build/load_balance.p4.p4info.txt", - "bmv2_json": "build/load_balance.json", - "table_entries": [ - { - "table": "MyIngress.ecmp_group", - "default_action": true, - "action_name": "MyIngress.drop", - "action_params": {} - }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] - }, - "action_name": "MyIngress.set_rewrite_src", - "action_params": { - "new_src": "10.0.1.10" - } - }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.10", - 32 - ] - }, - "action_name": "MyIngress.set_ecmp_select", - "action_params": { - "ecmp_base": 1, - "ecmp_count": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 0 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:01:01", - "nhop_ipv4": "10.0.1.1", - "port": 1 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 1 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:02:02", - "nhop_ipv4": "10.0.2.2", - "port": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 2 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:03:03", - "nhop_ipv4": "10.0.3.3", - "port": 3 - } - }, - { - "table": "MyEgress.send_frame", - "match": { - "standard_metadata.egress_port": 1 - }, - "action_name": "MyEgress.rewrite_mac", - "action_params": { - "smac": "00:00:00:01:01:00" - } - }, - { - "table": "MyEgress.send_frame", - "match": { - "standard_metadata.egress_port": 2 - }, - "action_name": "MyEgress.rewrite_mac", - "action_params": { - "smac": "00:00:00:01:02:00" - } - }, - { - "table": "MyEgress.send_frame", - "match": { - "standard_metadata.egress_port": 3 - }, - "action_name": "MyEgress.rewrite_mac", - "action_params": { - "smac": "00:00:00:01:03:00" - } - } - ] -} \ No newline at end of file + "target": "bmv2", + "p4info": "build/load_balance.p4.p4info.txt", + "bmv2_json": "build/load_balance.json", + "table_entries": [ + { + "table": "MyIngress.ecmp_group", + "default_action": true, + "action_name": "MyIngress.drop", + "action_params": {} + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] + }, + "action_name": "MyIngress.set_rewrite_src", + "action_params": { + "new_src": "10.0.1.10" + } + }, + { + "table": "MyIngress.ecmp_group", + "match": { + "hdr.ipv4.dstAddr": ["10.0.1.10", 32] + }, + "action_name": "MyIngress.set_ecmp_select", + "action_params": { + "ecmp_base": 1, + "ecmp_count": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 0 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:01:01", + "nhop_ipv4": "10.0.1.1", + "port": 1 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 1 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:02:02", + "nhop_ipv4": "10.0.2.2", + "port": 2 + } + }, + { + "table": "MyIngress.ecmp_nhop", + "match": { + "meta.ecmp_select": 2 + }, + "action_name": "MyIngress.set_nhop", + "action_params": { + "nhop_dmac": "08:00:00:00:03:03", + "nhop_ipv4": "10.0.3.3", + "port": 3 + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 1 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:01:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 2 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:02:00" + } + }, + { + "table": "MyEgress.send_frame", + "match": { + "standard_metadata.egress_port": 3 + }, + "action_name": "MyEgress.rewrite_mac", + "action_params": { + "smac": "00:00:00:01:03:00" + } + } + ] +} diff --git a/examples/process_migration/config/s2-runtime.json b/examples/process_migration/config/s2-runtime.json index 80e328d..12c2b4e 100644 --- a/examples/process_migration/config/s2-runtime.json +++ b/examples/process_migration/config/s2-runtime.json @@ -12,10 +12,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.2.2", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.2.2", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -26,10 +23,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -82,4 +76,4 @@ } } ] -} \ No newline at end of file +} diff --git a/examples/process_migration/config/s3-runtime.json b/examples/process_migration/config/s3-runtime.json index 703ede5..e3cd0b4 100644 --- a/examples/process_migration/config/s3-runtime.json +++ b/examples/process_migration/config/s3-runtime.json @@ -12,10 +12,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.3.3", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.3.3", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -26,10 +23,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -82,4 +76,4 @@ } } ] -} \ No newline at end of file +} diff --git a/examples/process_migration/config/s4-runtime.json b/examples/process_migration/config/s4-runtime.json index a165b6a..8986054 100644 --- a/examples/process_migration/config/s4-runtime.json +++ b/examples/process_migration/config/s4-runtime.json @@ -12,10 +12,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.4.4", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.4.4", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -26,10 +23,7 @@ { "table": "MyIngress.ecmp_group", "match": { - "hdr.ipv4.dstAddr": [ - "10.0.1.1", - 32 - ] + "hdr.ipv4.dstAddr": ["10.0.1.1", 32] }, "action_name": "MyIngress.set_ecmp_select", "action_params": { @@ -82,4 +76,4 @@ } } ] -} \ No newline at end of file +} From 148ee3693e50cd7f0dbe44e48ad211bccba36d46 Mon Sep 17 00:00:00 2001 From: Stanislav Kosorin Date: Sat, 10 Aug 2024 09:43:31 +0200 Subject: [PATCH 3/4] Add comment to the controller Makefile target --- examples/host_containers/Makefile | 1 + examples/process_migration/Makefile | 1 + examples/switch_container/Makefile | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/host_containers/Makefile b/examples/host_containers/Makefile index 64118a9..451640f 100644 --- a/examples/host_containers/Makefile +++ b/examples/host_containers/Makefile @@ -7,6 +7,7 @@ terminals: h1 h2 h3 h4 build: clean ./build.sh +# Sleep for 2 seconds to allow the switches to start controller: sleep 2 && ../../controller/controller.py --config config/switches.json diff --git a/examples/process_migration/Makefile b/examples/process_migration/Makefile index 581f69f..52b2716 100644 --- a/examples/process_migration/Makefile +++ b/examples/process_migration/Makefile @@ -8,6 +8,7 @@ terminals: h1 h2 h3 h4 build: clean ./build.sh +# Sleep for 2 seconds to allow the switches to start controller: sleep 2 && ../../controller/controller.py --config config/switches.json diff --git a/examples/switch_container/Makefile b/examples/switch_container/Makefile index 64118a9..451640f 100644 --- a/examples/switch_container/Makefile +++ b/examples/switch_container/Makefile @@ -7,6 +7,7 @@ terminals: h1 h2 h3 h4 build: clean ./build.sh +# Sleep for 2 seconds to allow the switches to start controller: sleep 2 && ../../controller/controller.py --config config/switches.json From 32c02b1889dac30ad26c5e2942c2b847a2b59ba2 Mon Sep 17 00:00:00 2001 From: Stanislav Kosorin Date: Sat, 10 Aug 2024 09:54:20 +0200 Subject: [PATCH 4/4] Add the lb_nodes field to the switches JSON config The lb_nodes field is a list of the nodes that the load balancer routes traffic to. This field consists of a list of dictionaries, where each dictionary contains the following fields: - ip: the IP address of the node - mac: the MAC address of the node - port: the switch port to use to route traffic to the node The controller uses this field to program the load balancer switch with proper match-action table entries. The controller tracks state of the table entries to allow updates after a container migration. --- controller/controller.py | 8 ++++- controller/node_manager.py | 28 +++++++++++---- controller/switch_controller.py | 19 ++++++++-- .../host_containers/config/s1-runtime.json | 35 ------------------- examples/host_containers/config/switches.json | 6 +++- .../process_migration/config/s1-runtime.json | 35 ------------------- .../process_migration/config/switches.json | 6 +++- .../switch_container/config/s1-runtime.json | 35 ------------------- .../switch_container/config/switches.json | 6 +++- 9 files changed, 61 insertions(+), 117 deletions(-) diff --git a/controller/controller.py b/controller/controller.py index 26a9077..4bbb60f 100755 --- a/controller/controller.py +++ b/controller/controller.py @@ -49,6 +49,9 @@ def main(config_file_path): raise Exception( "No master switch specified in the configuration file." ) + lb_nodes = master_config.get("lb_nodes", None) + if not lb_nodes: + raise Exception("No load balancer IP addresses specified.") master_controller = SwitchController( p4info_file_path=master_config["p4info_file_path"], @@ -59,8 +62,11 @@ def main(config_file_path): proto_dump_file=master_config["proto_dump_file"], initial_table_rules_file=master_config["runtime_file"], ) + global nodeManager - nodeManager = NodeManager(master_controller) + nodeManager = NodeManager( + switch_controller=master_controller, lb_nodes=lb_nodes + ) except KeyboardInterrupt: print("Shutting down.") diff --git a/controller/node_manager.py b/controller/node_manager.py index 62305ff..764ff2c 100644 --- a/controller/node_manager.py +++ b/controller/node_manager.py @@ -2,13 +2,29 @@ class NodeManager(object): - def __init__(self, switch_controller: SwitchController): + def __init__(self, switch_controller: SwitchController, lb_nodes): self.switch_controller = switch_controller # ipv4 -> ecmp_select_id - self.node_map = { - "10.0.2.2": 1, - "10.0.3.3": 2, - } + self.node_map = {} + for i, node in enumerate(lb_nodes): + # 0 is reserved for 10.0.1.1 (client), the rest for nodes + ip = node["ip"] + mac = node["mac"] + port = node["port"] + self.node_map[ip] = i + 1 + self.switch_controller.insertEcmpNhopEntry( + ecmp_select=i + 1, + dmac=mac, + ipv4=ip, + port=port, + update_type="INSERT", + ) + self.switch_controller.insertEcmpGroupEntry( + matchDstAddr=["10.0.1.10", 32], + ecmp_base=1, + ecmp_count=len(lb_nodes), + ) + self.switch_controller.readTableRules() def updateNode(self, old_ip, new_ip, dest_mac, egress_port): if new_ip in self.node_map: @@ -19,7 +35,7 @@ def updateNode(self, old_ip, new_ip, dest_mac, egress_port): ecmp_select_id = self.node_map.pop(old_ip) - self.switch_controller.upsertEcmpNhopEntry( + self.switch_controller.insertEcmpNhopEntry( ecmp_select=ecmp_select_id, dmac=dest_mac, ipv4=new_ip, diff --git a/controller/switch_controller.py b/controller/switch_controller.py index fe3e742..a2f3a91 100644 --- a/controller/switch_controller.py +++ b/controller/switch_controller.py @@ -67,7 +67,22 @@ def __init__( def __del__(self): ShutdownAllSwitchConnections() - def upsertEcmpNhopEntry( + def insertEcmpGroupEntry( + self, matchDstAddr, ecmp_base, ecmp_count, update_type="INSERT" + ): + table_entry = self.p4info_helper.buildTableEntry( + table_name="MyIngress.ecmp_group", + match_fields={"hdr.ipv4.dstAddr": matchDstAddr}, + action_name="MyIngress.set_ecmp_select", + action_params={"ecmp_base": ecmp_base, "ecmp_count": ecmp_count}, + ) + self.sw.WriteTableEntry(table_entry, update_type=update_type) + print( + f"Updated the 'ecmp_group' table on " + f"{self.sw.name=} with {matchDstAddr=}, {ecmp_base=}, {ecmp_count=}" + ) + + def insertEcmpNhopEntry( self, ecmp_select, dmac, ipv4, port, update_type="INSERT" ): table_entry = self.p4info_helper.buildTableEntry( @@ -93,7 +108,7 @@ def deleteEcmpNhopEntry(self, ecmp_select): f"{self.sw.name=} with {ecmp_select=}" ) - def upsertSendFrameEntry(self, egress_port, smac): + def insertSendFrameEntry(self, egress_port, smac): table_entry = self.p4info_helper.buildTableEntry( table_name="MyEgress.send_frame", match_fields={"standard_metadata.egress_port": egress_port}, diff --git a/examples/host_containers/config/s1-runtime.json b/examples/host_containers/config/s1-runtime.json index 733810a..6f95aec 100644 --- a/examples/host_containers/config/s1-runtime.json +++ b/examples/host_containers/config/s1-runtime.json @@ -19,17 +19,6 @@ "new_src": "10.0.1.10" } }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": ["10.0.1.10", 32] - }, - "action_name": "MyIngress.set_ecmp_select", - "action_params": { - "ecmp_base": 1, - "ecmp_count": 2 - } - }, { "table": "MyIngress.ecmp_nhop", "match": { @@ -42,30 +31,6 @@ "port": 1 } }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 1 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:02:02", - "nhop_ipv4": "10.0.2.2", - "port": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 2 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:03:03", - "nhop_ipv4": "10.0.3.3", - "port": 3 - } - }, { "table": "MyEgress.send_frame", "match": { diff --git a/examples/host_containers/config/switches.json b/examples/host_containers/config/switches.json index dd78560..d5e992f 100644 --- a/examples/host_containers/config/switches.json +++ b/examples/host_containers/config/switches.json @@ -7,7 +7,11 @@ "runtime_file": "./config/s1-runtime.json", "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", "bmv2_file_path": "../../load_balancer/build/load_balance.json", - "master": true + "master": true, + "lb_nodes": [ + { "ip": "10.0.2.2", "mac": "08:00:00:00:02:02", "port": 2 }, + { "ip": "10.0.3.3", "mac": "08:00:00:00:03:03", "port": 3 } + ] }, { "id": 1, diff --git a/examples/process_migration/config/s1-runtime.json b/examples/process_migration/config/s1-runtime.json index 733810a..6f95aec 100644 --- a/examples/process_migration/config/s1-runtime.json +++ b/examples/process_migration/config/s1-runtime.json @@ -19,17 +19,6 @@ "new_src": "10.0.1.10" } }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": ["10.0.1.10", 32] - }, - "action_name": "MyIngress.set_ecmp_select", - "action_params": { - "ecmp_base": 1, - "ecmp_count": 2 - } - }, { "table": "MyIngress.ecmp_nhop", "match": { @@ -42,30 +31,6 @@ "port": 1 } }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 1 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:02:02", - "nhop_ipv4": "10.0.2.2", - "port": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 2 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:03:03", - "nhop_ipv4": "10.0.3.3", - "port": 3 - } - }, { "table": "MyEgress.send_frame", "match": { diff --git a/examples/process_migration/config/switches.json b/examples/process_migration/config/switches.json index dd78560..d5e992f 100644 --- a/examples/process_migration/config/switches.json +++ b/examples/process_migration/config/switches.json @@ -7,7 +7,11 @@ "runtime_file": "./config/s1-runtime.json", "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", "bmv2_file_path": "../../load_balancer/build/load_balance.json", - "master": true + "master": true, + "lb_nodes": [ + { "ip": "10.0.2.2", "mac": "08:00:00:00:02:02", "port": 2 }, + { "ip": "10.0.3.3", "mac": "08:00:00:00:03:03", "port": 3 } + ] }, { "id": 1, diff --git a/examples/switch_container/config/s1-runtime.json b/examples/switch_container/config/s1-runtime.json index 733810a..6f95aec 100644 --- a/examples/switch_container/config/s1-runtime.json +++ b/examples/switch_container/config/s1-runtime.json @@ -19,17 +19,6 @@ "new_src": "10.0.1.10" } }, - { - "table": "MyIngress.ecmp_group", - "match": { - "hdr.ipv4.dstAddr": ["10.0.1.10", 32] - }, - "action_name": "MyIngress.set_ecmp_select", - "action_params": { - "ecmp_base": 1, - "ecmp_count": 2 - } - }, { "table": "MyIngress.ecmp_nhop", "match": { @@ -42,30 +31,6 @@ "port": 1 } }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 1 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:02:02", - "nhop_ipv4": "10.0.2.2", - "port": 2 - } - }, - { - "table": "MyIngress.ecmp_nhop", - "match": { - "meta.ecmp_select": 2 - }, - "action_name": "MyIngress.set_nhop", - "action_params": { - "nhop_dmac": "08:00:00:00:03:03", - "nhop_ipv4": "10.0.3.3", - "port": 3 - } - }, { "table": "MyEgress.send_frame", "match": { diff --git a/examples/switch_container/config/switches.json b/examples/switch_container/config/switches.json index 5b3d72a..6684bac 100644 --- a/examples/switch_container/config/switches.json +++ b/examples/switch_container/config/switches.json @@ -7,6 +7,10 @@ "runtime_file": "config/s1-runtime.json", "p4info_file_path": "../../load_balancer/build/load_balance.p4.p4info.txt", "bmv2_file_path": "../../load_balancer/build/load_balance.json", - "master": true + "master": true, + "lb_nodes": [ + { "ip": "10.0.2.2", "mac": "08:00:00:00:02:02", "port": 2 }, + { "ip": "10.0.3.3", "mac": "08:00:00:00:03:03", "port": 3 } + ] } ]