Tutorial: Automate GTP-U tunnel creation using Go
In the last tutorial, we created a GTP-U tunnel on a Ubuntu virtual machine using Open Vswitch. Here we will take the next step and write a Go program that programatically creates such tunnels.
Pre-requisites
- a Ubuntu 22.04 machine
Install OVS:
sudo apt update
sudo apt install openvswitch-switch
Create a folder named tunnel-go
:
mkdit tunnel-go
cd tunnel-go
Create a new go module:
go mod init tunnel-go
Create a main.go
file with an empty main function:
package main
func main() {}
Import Digital Ocean’s OVS Go library as well as the log standard library:
package main
import (
"log"
"github.com/digitalocean/go-openvswitch/ovs"
)
func main() {
}
Use the OVS library to create a client:
ovsClient := ovs.New(
ovs.Sudo(),
)
With this client, create a bridge named br0
:
if err := ovsClient.VSwitch.AddBridge(ovsBridge); err != nil {
log.Fatalf("failed to add bridge: %v", err)
}
Use the netdev datapath:
if err := ovsClient.VSwitch.Set.Bridge(ovsBridge, ovs.BridgeOptions{
DataPathType: ovs.DataPathTypeNetDev,
}); err != nil {
log.Fatalf("failed to set bridge: %v", err)
}
Create the enp6s0
and enp7s0
ports:
if err := ovsClient.VSwitch.AddPort(ovsBridge, ranPort); err != nil {
log.Fatalf("failed to add port: %v", err)
}
if err := ovsClient.VSwitch.AddPort(ovsBridge, dataPort); err != nil {
log.Fatalf("failed to add port: %v", err)
}
Create the GTP-U tunnel:
if err := ovsClient.VSwitch.AddPort(ovsBridge, gtpuPort); err != nil {
log.Fatalf("failed to add port: %v", err)
}
if err := ovsClient.VSwitch.Set.Interface(gtpuPort, ovs.InterfaceOptions{
Type: "gtpu",
RemoteIP: gtpuRemoteIP,
Key: gtpuTEID,
}); err != nil {
log.Fatalf("failed to set interface: %v", err)
}
There you go, you have created a program that can create GTP-U tunnels! 🎊
Here’s the complete code:
package main
import (
"log"
"github.com/digitalocean/go-openvswitch/ovs"
)
func main() {
CreateGTPUTunnel()
}
func CreateGTPUTunnel() {
var ovsBridge string = "br0"
var ranPort string = "ran"
var dataPort string = "data"
var gtpuPort string = "gtpu0"
var gtpuRemoteIP string = "172.31.1.1"
var gtpuTEID string = "5000"
ovsClient := ovs.New(
ovs.Sudo(),
)
// sudo ovs-vsctl add-br br0
if err := ovsClient.VSwitch.AddBridge(ovsBridge); err != nil {
log.Fatalf("failed to add bridge: %v", err)
}
// sudo ovs-vsctl set bridge br0 datapath_type=netdev
if err := ovsClient.VSwitch.Set.Bridge(ovsBridge, ovs.BridgeOptions{
DataPathType: ovs.DataPathTypeNetDev,
}); err != nil {
log.Fatalf("failed to set bridge: %v", err)
}
// sudo ovs-vsctl add-port br0 enp6s0
if err := ovsClient.VSwitch.AddPort(ovsBridge, ranPort); err != nil {
log.Fatalf("failed to add port: %v", err)
}
// sudo ovs-vsctl add-port br0 enp7s0
if err := ovsClient.VSwitch.AddPort(ovsBridge, dataPort); err != nil {
log.Fatalf("failed to add port: %v", err)
}
// sudo ovs-vsctl add-port br0 gtpu0
if err := ovsClient.VSwitch.AddPort(ovsBridge, gtpuPort); err != nil {
log.Fatalf("failed to add port: %v", err)
}
// sudo ovs-vsctl set int gtpu0 type=gtpu options:key=5000 options:remote_ip=172.31.1.1
if err := ovsClient.VSwitch.Set.Interface(gtpuPort, ovs.InterfaceOptions{
Type: "gtpu",
RemoteIP: gtpuRemoteIP,
Key: gtpuTEID,
}); err != nil {
log.Fatalf("failed to set interface: %v", err)
}
}