diff --git a/operator/src/switch/Dockerfile b/operator/src/switch/Dockerfile index 0d357a648986d4a45dff9ea5517bd8fe87548737..4f6fef8b86e21e1f89f83da4fb9fc9e379b4bd6f 100644 --- a/operator/src/switch/Dockerfile +++ b/operator/src/switch/Dockerfile @@ -1,4 +1,14 @@ -FROM golang:1.20 +FROM golang:1.20 AS build + +WORKDIR /usr/src/bin + +COPY ./main.go ./go.mod ./ + +RUN go build -v -o /usr/local/bin/l2sm-br ./... + +FROM ubuntu:latest + +COPY --from=build /usr/src/bin/ /usr/src/bin/ COPY ./vswitch.ovsschema /tmp/ @@ -8,17 +18,10 @@ RUN apt-get update && \ COPY ./setup_switch.sh /usr/local/bin/ -WORKDIR /usr/src/bin - -COPY ./main.go ./go.mod ./ - -RUN go build -v -o /usr/local/bin/l2sm-br ./... && \ - chmod +x /usr/local/bin/setup_switch.sh && \ +RUN chmod +x /usr/local/bin/setup_switch.sh && \ mkdir /etc/l2sm/ WORKDIR /usr/local/bin -CMD [ "./setup_switch.sh" ] - - \ No newline at end of file +CMD [ "./setup_switch.sh" ] \ No newline at end of file diff --git a/operator/src/switch/main.go b/operator/src/switch/main.go index da3c1f694d5ccc6aef833a14425ec38ef6c78e4e..e77d61da4cabac28dbb14a7998b5ab0690fa95f5 100644 --- a/operator/src/switch/main.go +++ b/operator/src/switch/main.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "errors" "flag" "fmt" "io/ioutil" @@ -21,23 +22,24 @@ type Node struct { // the second one is the path to the configuration file, in reference to the code. func main() { - configDir := os.Args[len(os.Args)-1] + configDir, vhostNumber, nodeName, controllerIP, err := takeArguments() - vhostNumber := flag.Int("n_vpods", 0, "number of pod interfaces that are going to be attached to the switch") - nodeName := flag.String("node_name", "", "name of the node the script is executed in. Required.") - flag.Parse() - - if *nodeName == "" { - fmt.Println("Please provide the node name using the --node_name flag") + if err != nil { + fmt.Println("Error:", err) return } - exec.Command("ovs-vsctl", "add-br", "brtun").Run() + err = initializeSwitch(controllerIP) - exec.Command("ip", "link", "set", "brtun", "up").Run() + if err != nil { + fmt.Println("Error:", err) + return + } + + fmt.Println("Switch initialized and connected to the controller.") // Set all virtual interfaces up, and connect them to the tunnel bridge: - for i := 1; i <= *vhostNumber; i++ { + for i := 1; i <= vhostNumber; i++ { vhost := fmt.Sprintf("vhost%d", i) cmd := exec.Command("ip", "link", "set", vhost, "up") // i.e: ip link set vhost1 up if err := cmd.Run(); err != nil { @@ -46,18 +48,80 @@ func main() { exec.Command("ovs-vsctl", "add-port", "brtun", vhost).Run() // i.e: ovs-vsctl add-port brtun vhost1 } + err = createVxlans(configDir, nodeName) + + if err != nil { + fmt.Println("Error:", err) + return + } +} + +func takeArguments() (string, int, string, string, error) { + configDir := os.Args[len(os.Args)-1] + + vhostNumber := flag.Int("n_vpods", 0, "number of pod interfaces that are going to be attached to the switch") + nodeName := flag.String("node_name", "", "name of the node the script is executed in. Required.") + controllerIP := flag.String("controller_ip", "", "ip where the SDN controller is listening using the OpenFlow13 protocol. Required") + + flag.Parse() + + switch { + case *nodeName == "": + return "", 0, "", "", errors.New("Node name is not defined") + case configDir == "": + return "", 0, "", "", errors.New("Config directory is not defined") + case *controllerIP == "": + return "", 0, "", "", errors.New("Controller IP is not defined") + } + + return configDir, *vhostNumber, *nodeName, *controllerIP, nil +} + +func initializeSwitch(controllerIP string) error { + + var err error + + err = exec.Command("ovs-vsctl", "add-br", "brtun").Run() + + if err != nil { + return err + } + + err = exec.Command("ip", "link", "set", "brtun", "up").Run() + + if err != nil { + return err + } + + err = exec.Command("ovs-vsctl", "set", "bridge", "brtun", "OpenFlow13").Run() + + if err != nil { + return err + } + + target := fmt.Sprintf("tcp:%s:6633", controllerIP) + + err = exec.Command("ovs-vsctl", "set-controller", "brtun", target).Run() + + if err != nil { + return err + } + return nil +} + +func createVxlans(configDir, nodeName string) error { + /// Read file and save in memory the JSON info data, err := ioutil.ReadFile(configDir) if err != nil { fmt.Println("Error reading input file:", err) - return + return err } var nodes []Node err = json.Unmarshal(data, &nodes) if err != nil { - fmt.Println("Error unmarshalling JSON:", err) - return + return err } // Search for the corresponding node in the configuration, according to the first passed parameter. @@ -68,7 +132,7 @@ func main() { // There's up to 2 ^ 24 possible vnis that are reduced to (2 ^24)/100 because of this measure (2 decimal digits are lost). So in total, a number of 167.772 virtual networks can be created. nodeVniRef := 5 for _, node := range nodes { - if node.Name == *nodeName { + if node.Name == nodeName { nodeIP := strings.TrimSpace(node.NodeIP) for _, neighbor := range node.NeighborNodes { neighborVniRef := 5 @@ -97,9 +161,9 @@ func main() { } _, err := exec.Command("ovs-vsctl", commandArgs...).Output() if err != nil { - fmt.Print(fmt.Errorf("Could not create vxlan between node %s and node %s.", node.Name, neighbor)) + return errors.New(fmt.Sprintf("Could not create vxlan between node %s and node %s.", node.Name, neighbor)) } else { - fmt.Print(fmt.Sprintf("Created vxlan between node %s and node %s.", node.Name, neighbor)) + fmt.Println(fmt.Sprintf("Created vxlan between node %s and node %s.", node.Name, neighbor)) } } neighborVniRef++ @@ -109,4 +173,5 @@ func main() { } nodeVniRef++ } + return nil } diff --git a/operator/src/switch/setup_switch.sh b/operator/src/switch/setup_switch.sh index ba85c706f1edeb9cc8544e8ad41103a01c59b18e..c0c43324b489c973451d208ea021296b0c08f362 100644 --- a/operator/src/switch/setup_switch.sh +++ b/operator/src/switch/setup_switch.sh @@ -6,4 +6,4 @@ ovs-vsctl --db=unix:/var/run/openvswitch/db.sock --no-wait init ovs-vswitchd --pidfile=/var/run/openvswitch/ovs-vswitchd.pid --detach -l2sm-br --n_vpods=$NVPODS --node_name=$NODENAME /etc/l2sm/switchConfig.json +l2sm-br --n_vpods=$NVPODS --node_name=$NODENAME --controller_ip=$CONTROLLERIP /etc/l2sm/switchConfig.json