Merge pull request #51 from clearlinux/tuntap

Add basic support for TUN/TAP link type and creation.
This commit is contained in:
Vish Ishaya 2015-10-10 14:16:40 -07:00
commit c48a5503c0
3 changed files with 79 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,7 +5,9 @@ import (
"encoding/binary"
"fmt"
"net"
"os"
"syscall"
"unsafe"
"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)

14
link_tuntap_linux.go Normal file
View File

@ -0,0 +1,14 @@
package netlink
// ideally golang.org/x/sys/unix would define IfReq but it only has
// IFNAMSIZ, hence this minimalistic implementation
const (
SizeOfIfReq = 40
IFNAMSIZ = 16
)
type ifReq struct {
Name [IFNAMSIZ]byte
Flags uint16
pad [SizeOfIfReq - IFNAMSIZ - 2]byte
}