rtnetlink/driver/macvlan.go
Jeroen Simonetti 5c41262525
Implement additional drivers (#280)
Add drivers for bridge, macvlan, vlan, vxlan and add helpers to
LinkService to use them (SetMaster, RemoveMaster)

Signed-off-by: Jeroen Simonetti <jeroen@simonetti.nl>
2025-10-30 22:55:44 +01:00

181 lines
4.3 KiB
Go

package driver
import (
"fmt"
"github.com/jsimonetti/rtnetlink/v2"
"github.com/jsimonetti/rtnetlink/v2/internal/unix"
"github.com/mdlayher/netlink"
)
// MacvlanMode represents the MACVLAN operating mode.
type MacvlanMode uint32
// MACVLAN modes.
const (
MacvlanModePrivate MacvlanMode = 0x1
MacvlanModeVEPA MacvlanMode = 0x2
MacvlanModeBridge MacvlanMode = 0x4
MacvlanModePassthru MacvlanMode = 0x8
MacvlanModeSource MacvlanMode = 0x10
)
// String returns a string representation of the MacvlanMode.
func (m MacvlanMode) String() string {
switch m {
case MacvlanModePrivate:
return "private"
case MacvlanModeVEPA:
return "vepa"
case MacvlanModeBridge:
return "bridge"
case MacvlanModePassthru:
return "passthru"
case MacvlanModeSource:
return "source"
default:
return fmt.Sprintf("unknown MacvlanMode value (%d)", m)
}
}
// MacvlanFlag represents MACVLAN flags.
type MacvlanFlag uint16
// MACVLAN flags.
const (
MacvlanFlagNopromisc MacvlanFlag = 0x1
MacvlanFlagNodst MacvlanFlag = 0x2
)
// MacvlanMacaddrMode represents the MACVLAN MAC address mode.
type MacvlanMacaddrMode uint32
// MACVLAN MAC address modes.
const (
MacvlanMacaddrAdd MacvlanMacaddrMode = 0x0
MacvlanMacaddrDel MacvlanMacaddrMode = 0x1
MacvlanMacaddrFlush MacvlanMacaddrMode = 0x2
MacvlanMacaddrSet MacvlanMacaddrMode = 0x3
)
// Macvlan represents a MACVLAN device configuration.
type Macvlan struct {
// Mode specifies the MACVLAN mode (private, vepa, bridge, passthru, source).
Mode *MacvlanMode
// Flags specifies MACVLAN flags (nopromisc, nodst).
Flags *MacvlanFlag
// MacaddrMode specifies the MAC address mode for source mode.
MacaddrMode *MacvlanMacaddrMode
// MacaddrData contains MAC addresses for source mode.
MacaddrData [][]byte
// MacaddrCount specifies the number of MAC addresses in source mode.
MacaddrCount *uint32
// BcQueueLen specifies the broadcast queue length.
BcQueueLen *uint32
// BcQueueLenUsed indicates if the broadcast queue length is being used.
BcQueueLenUsed *uint8
// BcCutoff specifies the broadcast cutoff value.
BcCutoff *int32
}
var _ rtnetlink.LinkDriver = &Macvlan{}
// New creates a new Macvlan instance.
func (m *Macvlan) New() rtnetlink.LinkDriver {
return &Macvlan{}
}
// Kind returns the MACVLAN interface kind.
func (m *Macvlan) Kind() string {
return "macvlan"
}
// Encode encodes the MACVLAN configuration into netlink attributes.
func (m *Macvlan) Encode(ae *netlink.AttributeEncoder) error {
if m.Mode != nil {
ae.Uint32(unix.IFLA_MACVLAN_MODE, uint32(*m.Mode))
}
if m.Flags != nil {
ae.Uint16(unix.IFLA_MACVLAN_FLAGS, uint16(*m.Flags))
}
if m.MacaddrMode != nil {
ae.Uint32(unix.IFLA_MACVLAN_MACADDR_MODE, uint32(*m.MacaddrMode))
}
if len(m.MacaddrData) > 0 {
ae.Nested(unix.IFLA_MACVLAN_MACADDR_DATA, func(nae *netlink.AttributeEncoder) error {
for i, mac := range m.MacaddrData {
nae.Bytes(uint16(i), mac)
}
return nil
})
}
if m.MacaddrCount != nil {
ae.Uint32(unix.IFLA_MACVLAN_MACADDR_COUNT, *m.MacaddrCount)
}
if m.BcQueueLen != nil {
ae.Uint32(unix.IFLA_MACVLAN_BC_QUEUE_LEN, *m.BcQueueLen)
}
if m.BcQueueLenUsed != nil {
ae.Uint8(unix.IFLA_MACVLAN_BC_QUEUE_LEN_USED, *m.BcQueueLenUsed)
}
if m.BcCutoff != nil {
ae.Int32(unix.IFLA_MACVLAN_BC_CUTOFF, *m.BcCutoff)
}
return nil
}
// Decode decodes netlink attributes into the MACVLAN configuration.
func (m *Macvlan) Decode(ad *netlink.AttributeDecoder) error {
for ad.Next() {
switch ad.Type() {
case unix.IFLA_MACVLAN_MODE:
mode := MacvlanMode(ad.Uint32())
m.Mode = &mode
case unix.IFLA_MACVLAN_FLAGS:
flags := MacvlanFlag(ad.Uint16())
m.Flags = &flags
case unix.IFLA_MACVLAN_MACADDR_MODE:
macaddrMode := MacvlanMacaddrMode(ad.Uint32())
m.MacaddrMode = &macaddrMode
case unix.IFLA_MACVLAN_MACADDR_DATA:
ad.Nested(func(nad *netlink.AttributeDecoder) error {
for nad.Next() {
m.MacaddrData = append(m.MacaddrData, nad.Bytes())
}
return nad.Err()
})
case unix.IFLA_MACVLAN_MACADDR_COUNT:
count := ad.Uint32()
m.MacaddrCount = &count
case unix.IFLA_MACVLAN_BC_QUEUE_LEN:
qlen := ad.Uint32()
m.BcQueueLen = &qlen
case unix.IFLA_MACVLAN_BC_QUEUE_LEN_USED:
used := ad.Uint8()
m.BcQueueLenUsed = &used
case unix.IFLA_MACVLAN_BC_CUTOFF:
cutoff := ad.Int32()
m.BcCutoff = &cutoff
}
}
return ad.Err()
}