Skip to content

Instantly share code, notes, and snippets.

@tormath1
Created April 9, 2021 16:08
Show Gist options
  • Save tormath1/d28b591b8619af41862be70b1eda02f6 to your computer and use it in GitHub Desktop.
Save tormath1/d28b591b8619af41862be70b1eda02f6 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"net"
"os"
"runtime"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)
var (
nsName = "go-ns"
brName = "br1"
veth1 = "172.18.0.20/16"
veth0 = "172.18.0.10/16"
b = "172.18.0.1/16"
)
func main() {
la := netlink.NewLinkAttrs()
la.Name = brName
br := &netlink.Bridge{LinkAttrs: la}
if err := netlink.LinkAdd(br); err != nil {
fmt.Printf("unable to add bridge %s: %v\n", la.Name, err)
os.Exit(1)
}
addr, err := netlink.ParseAddr(b)
if err != nil {
fmt.Printf("unable to parse addr: %v", err)
os.Exit(1)
}
if err := netlink.AddrAdd(br, addr); err != nil {
fmt.Printf("unable to add address: %v\n", err)
os.Exit(1)
}
if err := netlink.LinkSetUp(br); err != nil {
fmt.Printf("unable to set link up: %v\n", err)
os.Exit(1)
}
attr := netlink.NewLinkAttrs()
attr.Name = "veth0"
veth := &netlink.Veth{
PeerName: "veth1",
LinkAttrs: attr,
}
if err := netlink.LinkAdd(veth); err != nil {
fmt.Printf("unable to add link: %v\n", err)
os.Exit(1)
}
addr, err = netlink.ParseAddr(veth0)
if err != nil {
fmt.Printf("unable to parse addr: %v", err)
os.Exit(1)
}
if err := netlink.AddrAdd(veth, addr); err != nil {
fmt.Printf("unable to add address: %v\n", err)
os.Exit(1)
}
if err := netlink.LinkSetUp(veth); err != nil {
fmt.Printf("unable to set link up: %v", err)
os.Exit(1)
}
if err := netlink.LinkSetMaster(veth, br); err != nil {
fmt.Printf("unable to link veth to bridge: %v\n", err)
os.Exit(1)
}
// Lock the OS Thread so we don't accidentally switch namespaces
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// Save the current network namespace
origins, err := netns.Get()
if err != nil {
fmt.Printf("unable to get current network namespace: %v", err)
os.Exit(1)
}
defer origins.Close()
// Create a new network namespace
ns, err := netns.NewNamed(nsName)
if err != nil {
fmt.Printf("unable to create named namespace %s: %v\n", nsName, err)
os.Exit(1)
}
defer ns.Close()
if err := netns.Set(origins); err != nil {
fmt.Printf("unable to set namespace: %v\n", err)
os.Exit(1)
}
peer, err := netlink.LinkByName("veth1")
if err != nil {
fmt.Printf("unable to get link by name: %v", err)
os.Exit(1)
}
if err := netlink.LinkSetNsFd(peer, int(ns)); err != nil {
fmt.Printf("unable to set link into a new ns: %v\n", err)
os.Exit(1)
}
if err := netns.Set(ns); err != nil {
fmt.Printf("unable to set namespace: %v\n", err)
os.Exit(1)
}
addr, err = netlink.ParseAddr(veth1)
if err != nil {
fmt.Printf("unable to parse addr: %v", err)
os.Exit(1)
}
if err := netlink.AddrAdd(peer, addr); err != nil {
fmt.Printf("unable to add address: %v\n", err)
os.Exit(1)
}
if err := netlink.LinkSetUp(peer); err != nil {
fmt.Printf("unable to set link up: %v", err)
os.Exit(1)
}
// TODO: handle error
gtw, _, _ := net.ParseCIDR("172.18.0.1/32")
_, dst, _ := net.ParseCIDR("0.0.0.0/0")
if err := netlink.RouteAdd(&netlink.Route{
Scope: netlink.SCOPE_UNIVERSE,
Dst: dst,
LinkIndex: peer.Attrs().Index,
Gw: gtw,
}); err != nil {
fmt.Printf("unable to add default route: %v\n", err)
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment