Skip to content

Commit

Permalink
Add TCP connection support for OVS
Browse files Browse the repository at this point in the history
- Extend OVS connection options beyond Unix sockets
- Implement TCP endpoint configuration for marker binary
- Use -ovs-socket flag with format "tcp:<IP>:<PORT>"

Example usage: -ovs-socket tcp:127.0.0.1:6640

**What this PR does / why we need it**:

Add Support for ovs tcp connection

**Special notes for your reviewer**:

**Release note**:

```release-note
This feature allows for remote OVS connections, enhancing flexibility in network configurations.
User will be allowed to use tcp connection to OVS by specifying OVS
socket endpoint by using -ovs-socket flag with tcp endpoint "tcp:<IP>:<PORT>".
```

Signed-off-by: Tarek Abu-Hariri <[email protected]>
  • Loading branch information
tabuhariri committed Nov 12, 2024
1 parent b48c347 commit 646aad1
Showing 1 changed file with 76 additions and 33 deletions.
109 changes: 76 additions & 33 deletions cmd/marker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package main
import (
"flag"
"fmt"
"net"
"os"
"reflect"
"strings"
Expand All @@ -29,6 +30,12 @@ import (
"github.com/k8snetworkplumbingwg/ovs-cni/pkg/marker"
)

const (
UnixSocketType = "unix"
TcpSocketType = "tcp"
SocketConnectionTimeout = time.Minute
)

func main() {
nodeName := flag.String("node-name", "", "name of kubernetes node")
ovsSocket := flag.String("ovs-socket", "", "address of openvswitch database connection")
Expand All @@ -51,41 +58,12 @@ func main() {
glog.Fatal("node-name must be set")
}

if *ovsSocket == "" {
glog.Fatal("ovs-socket must be set")
}

var socketType, path string
ovsSocketTokens := strings.Split(*ovsSocket, ":")
if len(ovsSocketTokens) < 2 {
/*
* ovsSocket should consist of comma separated socket type and socket
* detail. If no socket type is specified, it is assumed to be a unix
* domain socket, for backwards compatibility.
*/
socketType = "unix"
path = *ovsSocket
} else {
socketType = ovsSocketTokens[0]
path = ovsSocketTokens[1]
}

if socketType == "unix" {
for {
_, err := os.Stat(path)
if err == nil {
glog.Info("Found the OVS socket")
break
} else if os.IsNotExist(err) {
glog.Infof("Given ovs-socket %q was not found, waiting for the socket to appear", path)
time.Sleep(time.Minute)
} else {
glog.Fatalf("Failed opening the OVS socket with: %v", err)
}
}
endpoint, err := parseOvsSocket(ovsSocket)
if err != nil {
glog.Fatalf("Failed to parse ovs socket: %v", err)
}

markerApp, err := marker.NewMarker(*nodeName, socketType+":"+path)
markerApp, err := marker.NewMarker(*nodeName, endpoint)
if err != nil {
glog.Fatalf("Failed to create a new marker object: %v", err)
}
Expand Down Expand Up @@ -137,3 +115,68 @@ func keepAlive(healthCheckFile string, healthCheckInterval int) {

}, time.Duration(healthCheckInterval)*time.Second)
}

func parseOvsSocket(ovsSocket *string) (string, error) {
if *ovsSocket == "" {
return "", fmt.Errorf("ovs-socket must be set")
}

var socketType, address string
ovsSocketTokens := strings.Split(*ovsSocket, ":")
if len(ovsSocketTokens) < 2 {
/*
* ovsSocket should consist of comma separated socket type and socket
* detail. If no socket type is specified, it is assumed to be a unix
* domain socket, for backwards compatibility.
*/
socketType = UnixSocketType
address = *ovsSocket
} else {
socketType = ovsSocketTokens[0]
if socketType == TcpSocketType {
if len(ovsSocketTokens) != 3 {
return "", fmt.Errorf("failed to parse OVS %s socket, must be in this format %s:<host>:<port>", socketType, socketType)
}
address = fmt.Sprintf("%s:%s", ovsSocketTokens[1], ovsSocketTokens[2])
} else {
// unix socket
address = ovsSocketTokens[1]
}
}
endpoint := fmt.Sprintf("%s:%s", socketType, address)

if socketType == UnixSocketType {
for {
_, err := os.Stat(address)
if err == nil {
glog.Info("Found the OVS socket")
break
} else if os.IsNotExist(err) {
glog.Infof("Given ovs-socket %q was not found, waiting for the socket to appear", address)
time.Sleep(SocketConnectionTimeout)
} else {
return "", fmt.Errorf("failed opening the OVS socket with: %v", err)
}
}
} else if socketType == TcpSocketType {
conn, err := net.DialTimeout(socketType, address, SocketConnectionTimeout)
if err == nil {
glog.Info("Successfully connected to TCP socket")
conn.Close()
return endpoint, nil
}

if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
return "", fmt.Errorf("connection to %s timed out", address)
} else if opErr, ok := err.(*net.OpError); ok {
if opErr.Op == "dial" {
return "", fmt.Errorf("connection to %s failed: %v", address, err)
} else {
return "", fmt.Errorf("unexpected error when connecting to %s: %v", address, err)
}
} else {
return "", fmt.Errorf("unexpected error when connecting to %s: %v", address, err)
}
}
return endpoint, nil
}

0 comments on commit 646aad1

Please sign in to comment.