Add basic support for TUN/TAP link type and creation.

This commit is contained in:
Dimitri John Ledkov 2015-09-25 10:28:19 +01:00
parent ecf47fd573
commit de4cc349a5
3 changed files with 82 additions and 1 deletions

26
link.go
View File

@ -1,6 +1,9 @@
package netlink
import "net"
import (
"net"
"syscall"
)
// Link represents a link device from netlink. Shared link attributes
// like name may be retrieved using the Attrs() method. Unique data
@ -136,6 +139,27 @@ func (macvtap Macvtap) Type() string {
return "macvtap"
}
type TuntapMode uint16
const (
TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN
TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP
)
// Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
type Tuntap struct {
LinkAttrs
Mode TuntapMode
}
func (tuntap *Tuntap) Attrs() *LinkAttrs {
return &tuntap.LinkAttrs
}
func (tuntap *Tuntap) Type() string {
return "tuntap"
}
// Veth devices must specify PeerName on create
type Veth struct {
LinkAttrs

View File

@ -5,6 +5,8 @@ import (
"encoding/binary"
"fmt"
"net"
"os"
"unsafe"
"syscall"
"github.com/vishvananda/netlink/nl"
@ -285,6 +287,44 @@ func LinkAdd(link Link) error {
return fmt.Errorf("LinkAttrs.Name cannot be empty!")
}
if tuntap, ok := link.(*Tuntap); ok {
// TODO: support user
// TODO: support group
// TODO: support non- one_queue
// TODO: support pi | vnet_hdr | multi_queue
// TODO: support non- exclusive
// TODO: support non- persistent
if (tuntap.Mode < syscall.IFF_TUN || tuntap.Mode > syscall.IFF_TAP) {
return fmt.Errorf("Tuntap.Mode %v unknown!", tuntap.Mode)
}
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
if err != nil {
return err
}
defer file.Close()
var req ifReq
req.Flags |= syscall.IFF_ONE_QUEUE
req.Flags |= syscall.IFF_TUN_EXCL
copy(req.Name[:15], base.Name)
req.Flags |= uint16(tuntap.Mode)
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
if errno != 0 {
return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed, errno %v", errno)
}
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), uintptr(syscall.TUNSETPERSIST), 1)
if errno != 0 {
return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
}
ensureIndex(base)
// can't set master during create, so set it afterwards
if base.MasterIndex != 0 {
// TODO: verify MasterIndex is actually a bridge?
return LinkSetMasterByIndex(link, base.MasterIndex)
}
return nil
}
req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)

17
link_tuntap_linux.go Normal file
View File

@ -0,0 +1,17 @@
package netlink
/*
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#define IFREQ_SIZE sizeof(struct ifreq)
*/
import "C"
type ifReq struct {
Name [C.IFNAMSIZ]byte
Flags uint16
pad [C.IFREQ_SIZE-C.IFNAMSIZ-2]byte
}