Skip to content

Commit

Permalink
Add link netkit
Browse files Browse the repository at this point in the history
This commit introduces a Driver interface alongside DriverData and SlaveDriverData fields
within the LinkInfo struct to accommodate driver-specific data encoding, addressing the limitation
where LinkInfo.Data and SlaveData fields were merely byte slices without support for specific data encoding.

LinkNetkit is implemented as a Driver interface. During encoding, if the DriverData interface is defined,
it is given precedence. For decoding, data of the kind "netkit" is converted into a LinkNetkit struct,
whereas all other types are retained as byte slices.

Signed-off-by: Birol Bilgin <[email protected]>
  • Loading branch information
brlbil committed Mar 4, 2024
1 parent 37c369e commit 14c25b6
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 8 deletions.
12 changes: 12 additions & 0 deletions internal/unix/types_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ const (
IFLA_INFO_SLAVE_KIND = linux.IFLA_INFO_SLAVE_KIND
IFLA_INFO_DATA = linux.IFLA_INFO_DATA
IFLA_INFO_SLAVE_DATA = linux.IFLA_INFO_SLAVE_DATA
IFLA_NETKIT_UNSPEC = 0x0 // TODO change these when latest golang.org/x/sys is released
IFLA_NETKIT_PEER_INFO = 0x1
IFLA_NETKIT_PRIMARY = 0x2
IFLA_NETKIT_POLICY = 0x3
IFLA_NETKIT_PEER_POLICY = 0x4
IFLA_NETKIT_MODE = 0x5
IFLA_XDP = linux.IFLA_XDP
IFLA_XDP_FD = linux.IFLA_XDP_FD
IFLA_XDP_ATTACHED = linux.IFLA_XDP_ATTACHED
Expand Down Expand Up @@ -147,4 +153,10 @@ const (
FRA_IP_PROTO = linux.FRA_IP_PROTO
FRA_SPORT_RANGE = linux.FRA_SPORT_RANGE
FRA_DPORT_RANGE = linux.FRA_DPORT_RANGE
NETKIT_NEXT = -0x1 // TODO change these when latest golang.org/x/sys is released
NETKIT_PASS = 0x0
NETKIT_DROP = 0x2
NETKIT_REDIRECT = 0x7
NETKIT_L2 = 0x0
NETKIT_L3 = 0x1
)
12 changes: 12 additions & 0 deletions internal/unix/types_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ const (
IFLA_INFO_SLAVE_KIND = 0x4
IFLA_INFO_DATA = 0x2
IFLA_INFO_SLAVE_DATA = 0x5
IFLA_NETKIT_UNSPEC = 0x0
IFLA_NETKIT_PEER_INFO = 0x1
IFLA_NETKIT_PRIMARY = 0x2
IFLA_NETKIT_POLICY = 0x3
IFLA_NETKIT_PEER_POLICY = 0x4
IFLA_NETKIT_MODE = 0x5
IFLA_XDP = 0x2b
IFLA_XDP_FD = 0x1
IFLA_XDP_ATTACHED = 0x2
Expand Down Expand Up @@ -143,4 +149,10 @@ const (
FRA_IP_PROTO = 0x16
FRA_SPORT_RANGE = 0x17
FRA_DPORT_RANGE = 0x18
NETKIT_NEXT = -0x1
NETKIT_PASS = 0x0
NETKIT_DROP = 0x2
NETKIT_REDIRECT = 0x7
NETKIT_L2 = 0x0
NETKIT_L3 = 0x1
)
91 changes: 83 additions & 8 deletions link.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,12 +547,20 @@ func (a *LinkStats64) unmarshalBinary(b []byte) error {
return nil
}

type Driver interface {
encode(*netlink.AttributeEncoder) error
decode(*netlink.AttributeDecoder) error
rtDriver()
}

// LinkInfo contains data for specific network types
type LinkInfo struct {
Kind string // Driver name
Data []byte // Driver specific configuration stored as nested Netlink messages
SlaveKind string // Slave driver name
SlaveData []byte // Slave driver specific configuration
Kind string // Driver name
Data []byte // Driver specific configuration stored as nested Netlink messages
DriverData Driver // Driver specific configuration stored as nested Netlink message, if defined Data is ignored
SlaveKind string // Slave driver name
SlaveData []byte // Slave driver specific configuration
SlaveDriverData Driver // Slave driver specific configuration, if defined SlaveData is ignored
}

func (i *LinkInfo) decode(ad *netlink.AttributeDecoder) error {
Expand All @@ -563,9 +571,21 @@ func (i *LinkInfo) decode(ad *netlink.AttributeDecoder) error {
case unix.IFLA_INFO_SLAVE_KIND:
i.SlaveKind = ad.String()
case unix.IFLA_INFO_DATA:
i.Data = ad.Bytes()
switch i.Kind {
case "netkit":
i.DriverData = &LinkNetkit{}
}
if i.DriverData == nil {
i.Data = ad.Bytes()
continue
}
ad.Nested(i.DriverData.decode)
case unix.IFLA_INFO_SLAVE_DATA:
i.SlaveData = ad.Bytes()
if i.SlaveDriverData == nil {
i.SlaveData = ad.Bytes()
continue
}
ad.Nested(i.SlaveDriverData.decode)
}
}

Expand All @@ -574,16 +594,71 @@ func (i *LinkInfo) decode(ad *netlink.AttributeDecoder) error {

func (i *LinkInfo) encode(ae *netlink.AttributeEncoder) error {
ae.String(unix.IFLA_INFO_KIND, i.Kind)
ae.Bytes(unix.IFLA_INFO_DATA, i.Data)
if i.DriverData != nil {
ae.Nested(unix.IFLA_INFO_DATA, i.DriverData.encode)
} else {
ae.Bytes(unix.IFLA_INFO_DATA, i.Data)
}

if len(i.SlaveData) > 0 {
ae.String(unix.IFLA_INFO_SLAVE_KIND, i.SlaveKind)
ae.Bytes(unix.IFLA_INFO_SLAVE_DATA, i.SlaveData)
if i.SlaveDriverData != nil {
ae.Nested(unix.IFLA_INFO_SLAVE_DATA, i.SlaveDriverData.encode)
} else {
ae.Bytes(unix.IFLA_INFO_SLAVE_DATA, i.SlaveData)
}
}

return nil
}

// LinkNetkit holds netkit link specific information
type LinkNetkit struct {
Mode uint32
Policy int32
PeerPolicy int32
Primary bool
PeerInfo *LinkMessage
}

var _ Driver = &LinkNetkit{}

func (n *LinkNetkit) decode(ad *netlink.AttributeDecoder) error {
for ad.Next() {
switch ad.Type() {
case unix.IFLA_NETKIT_MODE:
n.Mode = ad.Uint32()
case unix.IFLA_NETKIT_POLICY:
n.Policy = ad.Int32()
case unix.IFLA_NETKIT_PEER_POLICY:
n.PeerPolicy = ad.Int32()
case unix.IFLA_NETKIT_PRIMARY:
n.Primary = ad.Uint8() != 0
}
}
return nil
}

func (n *LinkNetkit) encode(ae *netlink.AttributeEncoder) error {
ae.Uint32(unix.IFLA_NETKIT_MODE, n.Mode)
ae.Int32(unix.IFLA_NETKIT_POLICY, n.Policy)
ae.Int32(unix.IFLA_NETKIT_PEER_POLICY, n.PeerPolicy)
if n.PeerInfo != nil {
n.PeerInfo.Family = unix.AF_UNSPEC
// we need to set the netkit.peerInfo.Flags and .Change according to primary link
// however we do not have this information here
b, err := n.PeerInfo.MarshalBinary()
if err != nil {
return err
}
ae.Bytes(unix.IFLA_NETKIT_PEER_INFO, b)
}
return nil
}

// rtDriver is an empty method to sattisfy the Driver interface.
func (n *LinkNetkit) rtDriver() {}

// LinkXDP holds Express Data Path specific information
type LinkXDP struct {
FD int32
Expand Down

0 comments on commit 14c25b6

Please sign in to comment.