support netkit

netkit device is merged to Linux upstream:
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=22360fad5889cbefe1eca695b0cc0273ab280b56

this PR add support to manage a netkit device in Golang

authored-by: tangchen <tangchen.1@bytedance.com>
This commit is contained in:
tc
2023-11-21 21:14:30 +08:00
committed by Alessandro Boch
parent 95ab6696a5
commit f1333cd79a
4 changed files with 276 additions and 9 deletions

View File

@@ -1634,6 +1634,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
}
case *Netkit:
if err := addNetkitAttrs(link, linkInfo, flags); err != nil {
return err
}
case *Veth:
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
@@ -1947,6 +1951,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Bridge{}
case "vlan":
link = &Vlan{}
case "netkit":
link = &Netkit{}
case "veth":
link = &Veth{}
case "wireguard":
@@ -2004,6 +2010,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
return nil, err
}
switch linkType {
case "netkit":
parseNetkitData(link, data)
case "vlan":
parseVlanData(link, data)
case "vxlan":
@@ -2544,6 +2552,80 @@ func (h *Handle) LinkSetGroup(link Link, group int) error {
return err
}
func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error {
if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil {
return fmt.Errorf("netkit doesn't support setting Ethernet")
}
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
// Kernel will return error if trying to change the mode of an existing netkit device
data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode)))
data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy)))
data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy)))
if (flag & unix.NLM_F_EXCL) == 0 {
// Modifying peer link attributes will not take effect
return nil
}
peer := data.AddRtAttr(nl.IFLA_NETKIT_PEER_INFO, nil)
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
if nk.peerLinkAttrs.Flags&net.FlagUp != 0 {
msg.Change = unix.IFF_UP
msg.Flags = unix.IFF_UP
}
if nk.peerLinkAttrs.Index != 0 {
msg.Index = int32(nk.peerLinkAttrs.Index)
}
peer.AddChild(msg)
if nk.peerLinkAttrs.Name != "" {
peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(nk.peerLinkAttrs.Name))
}
if nk.peerLinkAttrs.MTU > 0 {
peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(nk.peerLinkAttrs.MTU)))
}
if nk.peerLinkAttrs.GSOMaxSegs > 0 {
peer.AddRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSegs))
}
if nk.peerLinkAttrs.GSOMaxSize > 0 {
peer.AddRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSize))
}
if nk.peerLinkAttrs.GSOIPv4MaxSize > 0 {
peer.AddRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOIPv4MaxSize))
}
if nk.peerLinkAttrs.GROIPv4MaxSize > 0 {
peer.AddRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GROIPv4MaxSize))
}
if nk.peerLinkAttrs.Namespace != nil {
switch ns := nk.peerLinkAttrs.Namespace.(type) {
case NsPid:
peer.AddRtAttr(unix.IFLA_NET_NS_PID, nl.Uint32Attr(uint32(ns)))
case NsFd:
peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns)))
}
}
return nil
}
func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
netkit := link.(*Netkit)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_NETKIT_PRIMARY:
isPrimary := datum.Value[0:1][0]
if isPrimary != 0 {
netkit.isPrimary = true
}
case nl.IFLA_NETKIT_MODE:
netkit.Mode = NetkitMode(native.Uint32(datum.Value[0:4]))
case nl.IFLA_NETKIT_POLICY:
netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
case nl.IFLA_NETKIT_PEER_POLICY:
netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4]))
}
}
}
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
vlan := link.(*Vlan)
for _, datum := range data {