Files
openlan/pkg/network/tap_kernel.go
2025-04-13 15:33:35 +08:00

156 lines
2.7 KiB
Go
Executable File

package network
import (
"sync"
"github.com/luscis/openlan/pkg/libol"
"github.com/luscis/openlan/pkg/water"
)
type KernelTap struct {
lock sync.Mutex
device *water.Interface
master Bridger
tenant string
name string
config TapConfig
ipMtu int
}
func NewKernelTap(tenant string, c TapConfig) (*KernelTap, error) {
if c.Mtu == 0 {
c.Mtu = 1500
}
if c.Name == "auto" {
c.Name = Taps.GenName()
}
device, err := WaterNew(c)
if err != nil {
return nil, err
}
tap := &KernelTap{
tenant: tenant,
device: device,
name: device.Name(),
config: c,
ipMtu: c.Mtu,
}
Taps.Add(tap)
return tap, nil
}
func (t *KernelTap) Has(v uint) bool {
if v == UsClose {
return t.device == nil
} else if v == UsUp {
return t.device != nil
}
return false
}
func (t *KernelTap) Type() string {
return ProviderKer
}
func (t *KernelTap) Tenant() string {
return t.tenant
}
func (t *KernelTap) IsTun() bool {
return t.config.Type == TUN
}
func (t *KernelTap) Name() string {
return t.name
}
func (t *KernelTap) Read(p []byte) (int, error) {
t.lock.Lock()
if t.device == nil {
t.lock.Unlock()
return 0, libol.NewErr("Closed")
}
t.lock.Unlock()
if n, err := t.device.Read(p); err == nil {
return n, nil
} else {
return 0, err
}
}
func (t *KernelTap) Write(p []byte) (int, error) {
t.lock.Lock()
if t.device == nil {
t.lock.Unlock()
return 0, libol.NewErr("Closed")
}
t.lock.Unlock()
return t.device.Write(p)
}
func (t *KernelTap) Recv(p []byte) (int, error) {
return t.Read(p)
}
func (t *KernelTap) Send(p []byte) (int, error) {
return t.Write(p)
}
func (t *KernelTap) Close() error {
t.lock.Lock()
defer t.lock.Unlock()
libol.Debug("KernelTap.Close %s", t.name)
if t.device == nil {
return nil
}
if t.master != nil {
_ = t.master.DelSlave(t.name)
t.master = nil
}
err := t.device.Close()
Taps.Del(t.name)
t.device = nil
return err
}
func (t *KernelTap) Master() Bridger {
t.lock.Lock()
defer t.lock.Unlock()
return t.master
}
func (t *KernelTap) SetMaster(dev Bridger) error {
t.lock.Lock()
defer t.lock.Unlock()
if t.master == nil {
t.master = dev
}
return libol.NewErr("already to %s", t.master)
}
func (t *KernelTap) Up() {
t.lock.Lock()
defer t.lock.Unlock()
libol.Debug("KernelTap.Up %s", t.name)
if _, err := libol.IpLinkUp(t.name); err != nil {
libol.Warn("KernelTap.Up %s: %s", t.name, err)
}
}
func (t *KernelTap) Down() {
t.lock.Lock()
defer t.lock.Unlock()
libol.Debug("KernelTap.Down %s", t.name)
if _, err := libol.IpLinkDown(t.name); err != nil {
libol.Warn("KernelTap.Down %s: %s", t.name, err)
}
}
func (t *KernelTap) String() string {
return t.name
}
func (t *KernelTap) Mtu() int {
return t.ipMtu
}