build: update github.com/vishvananda/netlink to 1.3.0

This includes a breaking change:
acdc658b86
route.Dst is now a zero IPNet instead of nil

Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
This commit is contained in:
Etienne Champetier
2024-08-16 13:07:52 -04:00
parent 5188dc8a19
commit d924f05e12
67 changed files with 5484 additions and 773 deletions

View File

@@ -15,6 +15,38 @@ var L4ProtoMap = map[uint8]string{
17: "udp",
}
// From https://git.netfilter.org/libnetfilter_conntrack/tree/include/libnetfilter_conntrack/libnetfilter_conntrack_tcp.h
// enum tcp_state {
// TCP_CONNTRACK_NONE,
// TCP_CONNTRACK_SYN_SENT,
// TCP_CONNTRACK_SYN_RECV,
// TCP_CONNTRACK_ESTABLISHED,
// TCP_CONNTRACK_FIN_WAIT,
// TCP_CONNTRACK_CLOSE_WAIT,
// TCP_CONNTRACK_LAST_ACK,
// TCP_CONNTRACK_TIME_WAIT,
// TCP_CONNTRACK_CLOSE,
// TCP_CONNTRACK_LISTEN, /* obsolete */
// #define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN
// TCP_CONNTRACK_MAX,
// TCP_CONNTRACK_IGNORE
// };
const (
TCP_CONNTRACK_NONE = 0
TCP_CONNTRACK_SYN_SENT = 1
TCP_CONNTRACK_SYN_RECV = 2
TCP_CONNTRACK_ESTABLISHED = 3
TCP_CONNTRACK_FIN_WAIT = 4
TCP_CONNTRACK_CLOSE_WAIT = 5
TCP_CONNTRACK_LAST_ACK = 6
TCP_CONNTRACK_TIME_WAIT = 7
TCP_CONNTRACK_CLOSE = 8
TCP_CONNTRACK_LISTEN = 9
TCP_CONNTRACK_SYN_SENT2 = 9
TCP_CONNTRACK_MAX = 10
TCP_CONNTRACK_IGNORE = 11
)
// All the following constants are coming from:
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -31,6 +63,7 @@ var L4ProtoMap = map[uint8]string{
// IPCTNL_MSG_MAX
// };
const (
IPCTNL_MSG_CT_NEW = 0
IPCTNL_MSG_CT_GET = 1
IPCTNL_MSG_CT_DELETE = 2
)
@@ -88,7 +121,10 @@ const (
CTA_COUNTERS_REPLY = 10
CTA_USE = 11
CTA_ID = 12
CTA_ZONE = 18
CTA_TIMESTAMP = 20
CTA_LABELS = 22
CTA_LABELS_MASK = 23
)
// enum ctattr_tuple {
@@ -149,7 +185,10 @@ const (
// };
// #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
const (
CTA_PROTOINFO_UNSPEC = 0
CTA_PROTOINFO_TCP = 1
CTA_PROTOINFO_DCCP = 2
CTA_PROTOINFO_SCTP = 3
)
// enum ctattr_protoinfo_tcp {

View File

@@ -9,39 +9,56 @@ const (
)
const (
DEVLINK_CMD_GET = 1
DEVLINK_CMD_PORT_GET = 5
DEVLINK_CMD_PORT_SET = 6
DEVLINK_CMD_PORT_NEW = 7
DEVLINK_CMD_PORT_DEL = 8
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
DEVLINK_CMD_INFO_GET = 51
DEVLINK_CMD_GET = 1
DEVLINK_CMD_PORT_GET = 5
DEVLINK_CMD_PORT_SET = 6
DEVLINK_CMD_PORT_NEW = 7
DEVLINK_CMD_PORT_DEL = 8
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
DEVLINK_CMD_RESOURCE_DUMP = 36
DEVLINK_CMD_PARAM_GET = 38
DEVLINK_CMD_PARAM_SET = 39
DEVLINK_CMD_INFO_GET = 51
)
const (
DEVLINK_ATTR_BUS_NAME = 1
DEVLINK_ATTR_DEV_NAME = 2
DEVLINK_ATTR_PORT_INDEX = 3
DEVLINK_ATTR_PORT_TYPE = 4
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
DEVLINK_ATTR_ESWITCH_MODE = 25
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
DEVLINK_ATTR_PORT_FLAVOUR = 77
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
DEVLINK_ATTR_INFO_VERSION_STORED = 102
DEVLINK_ATTR_INFO_VERSION_NAME = 103
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
DEVLINK_ATTR_PORT_FUNCTION = 145
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
DEVLINK_ATTR_BUS_NAME = 1
DEVLINK_ATTR_DEV_NAME = 2
DEVLINK_ATTR_PORT_INDEX = 3
DEVLINK_ATTR_PORT_TYPE = 4
DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
DEVLINK_ATTR_PORT_NETDEV_NAME = 7
DEVLINK_ATTR_PORT_IBDEV_NAME = 8
DEVLINK_ATTR_ESWITCH_MODE = 25
DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
DEVLINK_ATTR_RESOURCE_LIST = 63 /* nested */
DEVLINK_ATTR_RESOURCE = 64 /* nested */
DEVLINK_ATTR_RESOURCE_NAME = 65 /* string */
DEVLINK_ATTR_RESOURCE_ID = 66 /* u64 */
DEVLINK_ATTR_RESOURCE_SIZE = 67 /* u64 */
DEVLINK_ATTR_RESOURCE_SIZE_NEW = 68 /* u64 */
DEVLINK_ATTR_RESOURCE_SIZE_VALID = 69 /* u8 */
DEVLINK_ATTR_RESOURCE_SIZE_MIN = 70 /* u64 */
DEVLINK_ATTR_RESOURCE_SIZE_MAX = 71 /* u64 */
DEVLINK_ATTR_RESOURCE_SIZE_GRAN = 72 /* u64 */
DEVLINK_ATTR_RESOURCE_UNIT = 73 /* u8 */
DEVLINK_ATTR_RESOURCE_OCC = 74 /* u64 */
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID = 75 /* u64 */
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS = 76 /* u64 */
DEVLINK_ATTR_PORT_FLAVOUR = 77
DEVLINK_ATTR_INFO_DRIVER_NAME = 98
DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
DEVLINK_ATTR_INFO_VERSION_FIXED = 100
DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
DEVLINK_ATTR_INFO_VERSION_STORED = 102
DEVLINK_ATTR_INFO_VERSION_NAME = 103
DEVLINK_ATTR_INFO_VERSION_VALUE = 104
DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
DEVLINK_ATTR_PORT_FUNCTION = 145
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
)
const (
@@ -94,3 +111,32 @@ const (
DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
)
const (
DEVLINK_RESOURCE_UNIT_ENTRY uint8 = 0
)
const (
DEVLINK_ATTR_PARAM = iota + 80 /* nested */
DEVLINK_ATTR_PARAM_NAME /* string */
DEVLINK_ATTR_PARAM_GENERIC /* flag */
DEVLINK_ATTR_PARAM_TYPE /* u8 */
DEVLINK_ATTR_PARAM_VALUES_LIST /* nested */
DEVLINK_ATTR_PARAM_VALUE /* nested */
DEVLINK_ATTR_PARAM_VALUE_DATA /* dynamic */
DEVLINK_ATTR_PARAM_VALUE_CMODE /* u8 */
)
const (
DEVLINK_PARAM_TYPE_U8 = 1
DEVLINK_PARAM_TYPE_U16 = 2
DEVLINK_PARAM_TYPE_U32 = 3
DEVLINK_PARAM_TYPE_STRING = 5
DEVLINK_PARAM_TYPE_BOOL = 6
)
const (
DEVLINK_PARAM_CMODE_RUNTIME = iota
DEVLINK_PARAM_CMODE_DRIVERINIT
DEVLINK_PARAM_CMODE_PERMANENT
)

View File

@@ -0,0 +1,21 @@
package nl
// id's of route attribute from https://elixir.bootlin.com/linux/v5.17.3/source/include/uapi/linux/lwtunnel.h#L38
// the value's size are specified in https://elixir.bootlin.com/linux/v5.17.3/source/net/ipv4/ip_tunnel_core.c#L928
const (
LWTUNNEL_IP6_UNSPEC = iota
LWTUNNEL_IP6_ID
LWTUNNEL_IP6_DST
LWTUNNEL_IP6_SRC
LWTUNNEL_IP6_HOPLIMIT
LWTUNNEL_IP6_TC
LWTUNNEL_IP6_FLAGS
LWTUNNEL_IP6_PAD // not implemented
LWTUNNEL_IP6_OPTS // not implemented
__LWTUNNEL_IP6_MAX
)

View File

@@ -88,6 +88,11 @@ const (
SET_ATTR_CREATE_MAX
)
const (
IPSET_ATTR_IPADDR_IPV4 = 1
IPSET_ATTR_IPADDR_IPV6 = 2
)
/* ADT specific attributes */
const (
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + iota + 1

View File

@@ -3,6 +3,7 @@ package nl
import (
"bytes"
"encoding/binary"
"fmt"
"unsafe"
)
@@ -30,6 +31,16 @@ const (
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
)
const (
IFLA_NETKIT_UNSPEC = iota
IFLA_NETKIT_PEER_INFO
IFLA_NETKIT_PRIMARY
IFLA_NETKIT_POLICY
IFLA_NETKIT_PEER_POLICY
IFLA_NETKIT_MODE
IFLA_NETKIT_MAX = IFLA_NETKIT_MODE
)
const (
VETH_INFO_UNSPEC = iota
VETH_INFO_PEER
@@ -85,7 +96,37 @@ const (
IFLA_BRPORT_PROXYARP
IFLA_BRPORT_LEARNING_SYNC
IFLA_BRPORT_PROXYARP_WIFI
IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI
IFLA_BRPORT_ROOT_ID
IFLA_BRPORT_BRIDGE_ID
IFLA_BRPORT_DESIGNATED_PORT
IFLA_BRPORT_DESIGNATED_COST
IFLA_BRPORT_ID
IFLA_BRPORT_NO
IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
IFLA_BRPORT_CONFIG_PENDING
IFLA_BRPORT_MESSAGE_AGE_TIMER
IFLA_BRPORT_FORWARD_DELAY_TIMER
IFLA_BRPORT_HOLD_TIMER
IFLA_BRPORT_FLUSH
IFLA_BRPORT_MULTICAST_ROUTER
IFLA_BRPORT_PAD
IFLA_BRPORT_MCAST_FLOOD
IFLA_BRPORT_MCAST_TO_UCAST
IFLA_BRPORT_VLAN_TUNNEL
IFLA_BRPORT_BCAST_FLOOD
IFLA_BRPORT_GROUP_FWD_MASK
IFLA_BRPORT_NEIGH_SUPPRESS
IFLA_BRPORT_ISOLATED
IFLA_BRPORT_BACKUP_PORT
IFLA_BRPORT_MRP_RING_OPEN
IFLA_BRPORT_MRP_IN_OPEN
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT
IFLA_BRPORT_LOCKED
IFLA_BRPORT_MAB
IFLA_BRPORT_MCAST_N_GROUPS
IFLA_BRPORT_MCAST_MAX_GROUPS
IFLA_BRPORT_MAX = IFLA_BRPORT_MCAST_MAX_GROUPS
)
const (
@@ -103,7 +144,9 @@ const (
IFLA_MACVLAN_MACADDR
IFLA_MACVLAN_MACADDR_DATA
IFLA_MACVLAN_MACADDR_COUNT
IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS
IFLA_MACVLAN_BC_QUEUE_LEN
IFLA_MACVLAN_BC_QUEUE_LEN_USED
IFLA_MACVLAN_MAX = IFLA_MACVLAN_BC_QUEUE_LEN_USED
)
const (
@@ -186,7 +229,10 @@ const (
IFLA_GENEVE_UDP_ZERO_CSUM6_TX
IFLA_GENEVE_UDP_ZERO_CSUM6_RX
IFLA_GENEVE_LABEL
IFLA_GENEVE_MAX = IFLA_GENEVE_LABEL
IFLA_GENEVE_TTL_INHERIT
IFLA_GENEVE_DF
IFLA_GENEVE_INNER_PROTO_INHERIT
IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT
)
const (
@@ -244,7 +290,15 @@ const (
IFLA_VF_TRUST /* Trust state of VF */
IFLA_VF_IB_NODE_GUID /* VF Infiniband node GUID */
IFLA_VF_IB_PORT_GUID /* VF Infiniband port GUID */
IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
IFLA_VF_VLAN_LIST /* nested list of vlans, option for QinQ */
IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
)
const (
IFLA_VF_VLAN_INFO_UNSPEC = iota
IFLA_VF_VLAN_INFO /* VLAN ID, QoS and VLAN protocol */
__IFLA_VF_VLAN_INFO_MAX
)
const (
@@ -269,6 +323,7 @@ const (
const (
SizeofVfMac = 0x24
SizeofVfVlan = 0x0c
SizeofVfVlanInfo = 0x10
SizeofVfTxRate = 0x08
SizeofVfRate = 0x0c
SizeofVfSpoofchk = 0x08
@@ -324,6 +379,49 @@ func (msg *VfVlan) Serialize() []byte {
return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:]
}
func DeserializeVfVlanList(b []byte) ([]*VfVlanInfo, error) {
var vfVlanInfoList []*VfVlanInfo
attrs, err := ParseRouteAttr(b)
if err != nil {
return nil, err
}
for _, element := range attrs {
if element.Attr.Type == IFLA_VF_VLAN_INFO {
vfVlanInfoList = append(vfVlanInfoList, DeserializeVfVlanInfo(element.Value))
}
}
if len(vfVlanInfoList) == 0 {
return nil, fmt.Errorf("VF vlan list is defined but no vf vlan info elements were found")
}
return vfVlanInfoList, nil
}
// struct ifla_vf_vlan_info {
// __u32 vf;
// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
// __u32 qos;
// __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
// };
type VfVlanInfo struct {
VfVlan
VlanProto uint16
}
func DeserializeVfVlanInfo(b []byte) *VfVlanInfo {
return &VfVlanInfo{
*(*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])),
binary.BigEndian.Uint16(b[SizeofVfVlan:SizeofVfVlanInfo]),
}
}
func (msg *VfVlanInfo) Serialize() []byte {
return (*(*[SizeofVfVlanInfo]byte)(unsafe.Pointer(msg)))[:]
}
// struct ifla_vf_tx_rate {
// __u32 vf;
// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */

View File

@@ -6,6 +6,7 @@ import (
"encoding/binary"
"fmt"
"net"
"os"
"runtime"
"sync"
"sync/atomic"
@@ -330,6 +331,19 @@ func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
return msg
}
type Uint32Bitfield struct {
Value uint32
Selector uint32
}
func (a *Uint32Bitfield) Serialize() []byte {
return (*(*[SizeofUint32Bitfield]byte)(unsafe.Pointer(a)))[:]
}
func DeserializeUint32Bitfield(data []byte) *Uint32Bitfield {
return (*Uint32Bitfield)(unsafe.Pointer(&data[0:SizeofUint32Bitfield][0]))
}
type Uint32Attribute struct {
Type uint16
Value uint32
@@ -475,10 +489,30 @@ func (req *NetlinkRequest) AddRawData(data []byte) {
req.RawData = append(req.RawData, data...)
}
// Execute the request against a the given sockType.
// Execute the request against the given sockType.
// Returns a list of netlink messages in serialized format, optionally filtered
// by resType.
func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
var res [][]byte
err := req.ExecuteIter(sockType, resType, func(msg []byte) bool {
res = append(res, msg)
return true
})
if err != nil {
return nil, err
}
return res, nil
}
// ExecuteIter executes the request against the given sockType.
// Calls the provided callback func once for each netlink message.
// If the callback returns false, it is not called again, but
// the remaining messages are consumed/discarded.
//
// Thread safety: ExecuteIter holds a lock on the socket until
// it finishes iteration so the callback must not call back into
// the netlink API.
func (req *NetlinkRequest) ExecuteIter(sockType int, resType uint16, f func(msg []byte) bool) error {
var (
s *NetlinkSocket
err error
@@ -495,18 +529,18 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
if s == nil {
s, err = getNetlinkSocket(sockType)
if err != nil {
return nil, err
return err
}
if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil {
return nil, err
return err
}
if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil {
return nil, err
return err
}
if EnableErrorMessageReporting {
if err := s.SetExtAck(true); err != nil {
return nil, err
return err
}
}
@@ -517,36 +551,44 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
}
if err := s.Send(req); err != nil {
return nil, err
return err
}
pid, err := s.GetPid()
if err != nil {
return nil, err
return err
}
var res [][]byte
done:
for {
msgs, from, err := s.Receive()
if err != nil {
return nil, err
return err
}
if from.Pid != PidKernel {
return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel)
}
for _, m := range msgs {
if m.Header.Seq != req.Seq {
if sharedSocket {
continue
}
return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq)
}
if m.Header.Pid != pid {
continue
}
if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 {
return syscall.Errno(unix.EINTR)
}
if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR {
// NLMSG_DONE might have no payload, if so assume no error.
if m.Header.Type == unix.NLMSG_DONE && len(m.Data) == 0 {
break done
}
native := NativeEndian()
errno := int32(native.Uint32(m.Data[0:4]))
if errno == 0 {
@@ -556,7 +598,7 @@ done:
err = syscall.Errno(-errno)
unreadData := m.Data[4:]
if m.Header.Flags|unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr {
if m.Header.Flags&unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr {
// Skip the echoed request message.
echoReqH := (*syscall.NlMsghdr)(unsafe.Pointer(&unreadData[0]))
unreadData = unreadData[nlmAlignOf(int(echoReqH.Len)):]
@@ -568,8 +610,7 @@ done:
switch attr.Type {
case NLMSGERR_ATTR_MSG:
err = fmt.Errorf("%w: %s", err, string(attrData))
err = fmt.Errorf("%w: %s", err, unix.ByteSliceToString(attrData))
default:
// TODO: handle other NLMSGERR_ATTR types
}
@@ -578,18 +619,26 @@ done:
}
}
return nil, err
return err
}
if resType != 0 && m.Header.Type != resType {
continue
}
res = append(res, m.Data)
if cont := f(m.Data); !cont {
// Drain the rest of the messages from the kernel but don't
// pass them to the iterator func.
f = dummyMsgIterFunc
}
if m.Header.Flags&unix.NLM_F_MULTI == 0 {
break done
}
}
}
return res, nil
return nil
}
func dummyMsgIterFunc(msg []byte) bool {
return true
}
// Create a new netlink request from proto and flags
@@ -607,8 +656,9 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
}
type NetlinkSocket struct {
fd int32
lsa unix.SockaddrNetlink
fd int32
file *os.File
lsa unix.SockaddrNetlink
sync.Mutex
}
@@ -617,8 +667,13 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
if err != nil {
return nil, err
}
err = unix.SetNonblock(fd, true)
if err != nil {
return nil, err
}
s := &NetlinkSocket{
fd: int32(fd),
fd: int32(fd),
file: os.NewFile(uintptr(fd), "netlink"),
}
s.lsa.Family = unix.AF_NETLINK
if err := unix.Bind(fd, &s.lsa); err != nil {
@@ -649,12 +704,14 @@ func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSock
// In case of success, the caller is expected to execute the returned function
// at the end of the code that needs to be executed in the network namespace.
// Example:
// func jobAt(...) error {
// d, err := executeInNetns(...)
// if err != nil { return err}
// defer d()
// < code which needs to be executed in specific netns>
// }
//
// func jobAt(...) error {
// d, err := executeInNetns(...)
// if err != nil { return err}
// defer d()
// < code which needs to be executed in specific netns>
// }
//
// TODO: his function probably belongs to netns pkg.
func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) {
var (
@@ -703,8 +760,13 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
if err != nil {
return nil, err
}
err = unix.SetNonblock(fd, true)
if err != nil {
return nil, err
}
s := &NetlinkSocket{
fd: int32(fd),
fd: int32(fd),
file: os.NewFile(uintptr(fd), "netlink"),
}
s.lsa.Family = unix.AF_NETLINK
@@ -733,33 +795,36 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne
}
func (s *NetlinkSocket) Close() {
fd := int(atomic.SwapInt32(&s.fd, -1))
unix.Close(fd)
s.file.Close()
}
func (s *NetlinkSocket) GetFd() int {
return int(atomic.LoadInt32(&s.fd))
return int(s.fd)
}
func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
fd := int(atomic.LoadInt32(&s.fd))
if fd < 0 {
return fmt.Errorf("Send called on a closed socket")
}
if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil {
return err
}
return nil
return unix.Sendto(int(s.fd), request.Serialize(), 0, &s.lsa)
}
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) {
fd := int(atomic.LoadInt32(&s.fd))
if fd < 0 {
return nil, nil, fmt.Errorf("Receive called on a closed socket")
rawConn, err := s.file.SyscallConn()
if err != nil {
return nil, nil, err
}
var (
fromAddr *unix.SockaddrNetlink
rb [RECEIVE_BUFFER_SIZE]byte
nr int
from unix.Sockaddr
innerErr error
)
err = rawConn.Read(func(fd uintptr) (done bool) {
nr, from, innerErr = unix.Recvfrom(int(fd), rb[:], 0)
return innerErr != unix.EWOULDBLOCK
})
if innerErr != nil {
err = innerErr
}
var fromAddr *unix.SockaddrNetlink
var rb [RECEIVE_BUFFER_SIZE]byte
nr, from, err := unix.Recvfrom(fd, rb[:], 0)
if err != nil {
return nil, nil, err
}
@@ -770,8 +835,9 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli
if nr < unix.NLMSG_HDRLEN {
return nil, nil, fmt.Errorf("Got short response from netlink")
}
rb2 := make([]byte, nr)
copy(rb2, rb[:nr])
msgLen := nlmAlignOf(nr)
rb2 := make([]byte, msgLen)
copy(rb2, rb[:msgLen])
nl, err := syscall.ParseNetlinkMessage(rb2)
if err != nil {
return nil, nil, err
@@ -793,6 +859,15 @@ func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error {
return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout)
}
// SetReceiveBufferSize allows to set a receive buffer size on the socket
func (s *NetlinkSocket) SetReceiveBufferSize(size int, force bool) error {
opt := unix.SO_RCVBUF
if force {
opt = unix.SO_RCVBUFFORCE
}
return unix.SetsockoptInt(int(s.fd), unix.SOL_SOCKET, opt, size)
}
// SetExtAck requests error messages to be reported on the socket
func (s *NetlinkSocket) SetExtAck(enable bool) error {
var enableN int
@@ -804,8 +879,7 @@ func (s *NetlinkSocket) SetExtAck(enable bool) error {
}
func (s *NetlinkSocket) GetPid() (uint32, error) {
fd := int(atomic.LoadInt32(&s.fd))
lsa, err := unix.Getsockname(fd)
lsa, err := unix.Getsockname(int(s.fd))
if err != nil {
return 0, err
}
@@ -849,6 +923,12 @@ func Uint16Attr(v uint16) []byte {
return bytes
}
func BEUint16Attr(v uint16) []byte {
bytes := make([]byte, 2)
binary.BigEndian.PutUint16(bytes, v)
return bytes
}
func Uint32Attr(v uint32) []byte {
native := NativeEndian()
bytes := make([]byte, 4)
@@ -856,6 +936,12 @@ func Uint32Attr(v uint32) []byte {
return bytes
}
func BEUint32Attr(v uint32) []byte {
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, v)
return bytes
}
func Uint64Attr(v uint64) []byte {
native := NativeEndian()
bytes := make([]byte, 8)
@@ -863,6 +949,12 @@ func Uint64Attr(v uint64) []byte {
return bytes
}
func BEUint64Attr(v uint64) []byte {
bytes := make([]byte, 8)
binary.BigEndian.PutUint64(bytes, v)
return bytes
}
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
var attrs []syscall.NetlinkRouteAttr
for len(b) >= unix.SizeofRtAttr {
@@ -877,6 +969,22 @@ func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
return attrs, nil
}
// ParseRouteAttrAsMap parses provided buffer that contains raw RtAttrs and returns a map of parsed
// atttributes indexed by attribute type or error if occured.
func ParseRouteAttrAsMap(b []byte) (map[uint16]syscall.NetlinkRouteAttr, error) {
attrMap := make(map[uint16]syscall.NetlinkRouteAttr)
attrs, err := ParseRouteAttr(b)
if err != nil {
return nil, err
}
for _, attr := range attrs {
attrMap[attr.Attr.Type] = attr
}
return attrMap, nil
}
func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) {
a := (*unix.RtAttr)(unsafe.Pointer(&b[0]))
if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) {

View File

@@ -48,7 +48,9 @@ type RtNexthop struct {
}
func DeserializeRtNexthop(b []byte) *RtNexthop {
return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))
return &RtNexthop{
RtNexthop: *((*unix.RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))),
}
}
func (msg *RtNexthop) Len() int {

View File

@@ -12,6 +12,7 @@ const (
SEG6_LOCAL_NH6
SEG6_LOCAL_IIF
SEG6_LOCAL_OIF
SEG6_LOCAL_BPF
__SEG6_LOCAL_MAX
)
const (
@@ -34,6 +35,7 @@ const (
SEG6_LOCAL_ACTION_END_S // 12
SEG6_LOCAL_ACTION_END_AS // 13
SEG6_LOCAL_ACTION_END_AM // 14
SEG6_LOCAL_ACTION_END_BPF // 15
__SEG6_LOCAL_ACTION_MAX
)
const (
@@ -71,6 +73,8 @@ func SEG6LocalActionString(action int) string {
return "End.AS"
case SEG6_LOCAL_ACTION_END_AM:
return "End.AM"
case SEG6_LOCAL_ACTION_END_BPF:
return "End.BPF"
}
return "unknown"
}

View File

@@ -46,6 +46,7 @@ const (
// socket diags related
const (
SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */
SOCK_DESTROY = 21
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
)

View File

@@ -1,8 +1,13 @@
package nl
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"unsafe"
"golang.org/x/sys/unix"
)
// LinkLayer
@@ -42,7 +47,14 @@ const (
TCA_FCNT
TCA_STATS2
TCA_STAB
TCA_MAX = TCA_STAB
TCA_PAD
TCA_DUMP_INVISIBLE
TCA_CHAIN
TCA_HW_OFFLOAD
TCA_INGRESS_BLOCK
TCA_EGRESS_BLOCK
TCA_DUMP_FLAGS
TCA_MAX = TCA_DUMP_FLAGS
)
const (
@@ -56,6 +68,12 @@ const (
TCA_ACT_OPTIONS
TCA_ACT_INDEX
TCA_ACT_STATS
TCA_ACT_PAD
TCA_ACT_COOKIE
TCA_ACT_FLAGS
TCA_ACT_HW_STATS
TCA_ACT_USED_HW_STATS
TCA_ACT_IN_HW_COUNT
TCA_ACT_MAX
)
@@ -71,7 +89,11 @@ const (
TCA_STATS_RATE_EST
TCA_STATS_QUEUE
TCA_STATS_APP
TCA_STATS_MAX = TCA_STATS_APP
TCA_STATS_RATE_EST64
TCA_STATS_PAD
TCA_STATS_BASIC_HW
TCA_STATS_PKT64
TCA_STATS_MAX = TCA_STATS_PKT64
)
const (
@@ -83,12 +105,13 @@ const (
SizeofTcNetemCorr = 0x0c
SizeofTcNetemReorder = 0x08
SizeofTcNetemCorrupt = 0x08
SizeOfTcNetemRate = 0x10
SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c
SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14
SizeofTcHtbGlob = 0x14
SizeofTcU32Key = 0x10
SizeofTcU32Sel = 0x10 // without keys
SizeofTcGen = 0x14
SizeofTcGen = 0x16
SizeofTcConnmark = SizeofTcGen + 0x04
SizeofTcCsum = SizeofTcGen + 0x04
SizeofTcMirred = SizeofTcGen + 0x08
@@ -98,6 +121,7 @@ const (
SizeofTcSfqQopt = 0x0b
SizeofTcSfqRedStats = 0x18
SizeofTcSfqQoptV1 = SizeofTcSfqQopt + SizeofTcSfqRedStats + 0x1c
SizeofUint32Bitfield = 0x8
)
// struct tcmsg {
@@ -131,6 +155,18 @@ func (x *TcMsg) Serialize() []byte {
return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:]
}
type Tcf struct {
Install uint64
LastUse uint64
Expires uint64
FirstUse uint64
}
func DeserializeTcf(b []byte) *Tcf {
const size = int(unsafe.Sizeof(Tcf{}))
return (*Tcf)(unsafe.Pointer(&b[0:size][0]))
}
// struct tcamsg {
// unsigned char tca_family;
// unsigned char tca__pad1;
@@ -337,6 +373,26 @@ func (x *TcNetemCorrupt) Serialize() []byte {
return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:]
}
// TcNetemRate is a struct that represents the rate of a netem qdisc
type TcNetemRate struct {
Rate uint32
PacketOverhead int32
CellSize uint32
CellOverhead int32
}
func (msg *TcNetemRate) Len() int {
return SizeofTcRateSpec
}
func DeserializeTcNetemRate(b []byte) *TcNetemRate {
return (*TcNetemRate)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0]))
}
func (msg *TcNetemRate) Serialize() []byte {
return (*(*[SizeOfTcNetemRate]byte)(unsafe.Pointer(msg)))[:]
}
// struct tc_tbf_qopt {
// struct tc_ratespec rate;
// struct tc_ratespec peakrate;
@@ -804,7 +860,8 @@ const (
TCA_SKBEDIT_MARK
TCA_SKBEDIT_PAD
TCA_SKBEDIT_PTYPE
TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK
TCA_SKBEDIT_MASK
TCA_SKBEDIT_MAX
)
type TcSkbEdit struct {
@@ -891,6 +948,10 @@ const (
TCA_FQ_FLOW_REFILL_DELAY // flow credit refill delay in usec
TCA_FQ_ORPHAN_MASK // mask applied to orphaned skb hashes
TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate
TCA_FQ_CE_THRESHOLD // DCTCP-like CE-marking threshold
TCA_FQ_TIMER_SLACK // timer slack
TCA_FQ_HORIZON // time horizon in us
TCA_FQ_HORIZON_DROP // drop packets beyond horizon, or cap their EDT
)
const (
@@ -1018,6 +1079,9 @@ const (
__TCA_FLOWER_MAX
)
const TCA_CLS_FLAGS_SKIP_HW = 1 << 0 /* don't offload filter to HW */
const TCA_CLS_FLAGS_SKIP_SW = 1 << 1 /* don't use filter in SW */
// struct tc_sfq_qopt {
// unsigned quantum; /* Bytes per round allocated to flow */
// int perturb_period; /* Period of hash perturbation */
@@ -1046,14 +1110,14 @@ func (x *TcSfqQopt) Serialize() []byte {
return (*(*[SizeofTcSfqQopt]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_sfqred_stats {
// __u32 prob_drop; /* Early drops, below max threshold */
// __u32 forced_drop; /* Early drops, after max threshold */
// __u32 prob_mark; /* Marked packets, below max threshold */
// __u32 forced_mark; /* Marked packets, after max threshold */
// __u32 prob_mark_head; /* Marked packets, below max threshold */
// __u32 forced_mark_head;/* Marked packets, after max threshold */
// };
// struct tc_sfqred_stats {
// __u32 prob_drop; /* Early drops, below max threshold */
// __u32 forced_drop; /* Early drops, after max threshold */
// __u32 prob_mark; /* Marked packets, below max threshold */
// __u32 forced_mark; /* Marked packets, after max threshold */
// __u32 prob_mark_head; /* Marked packets, below max threshold */
// __u32 forced_mark_head;/* Marked packets, after max threshold */
// };
type TcSfqRedStats struct {
ProbDrop uint32
ForcedDrop uint32
@@ -1075,22 +1139,26 @@ func (x *TcSfqRedStats) Serialize() []byte {
return (*(*[SizeofTcSfqRedStats]byte)(unsafe.Pointer(x)))[:]
}
// struct tc_sfq_qopt_v1 {
// struct tc_sfq_qopt v0;
// unsigned int depth; /* max number of packets per flow */
// unsigned int headdrop;
// struct tc_sfq_qopt_v1 {
// struct tc_sfq_qopt v0;
// unsigned int depth; /* max number of packets per flow */
// unsigned int headdrop;
//
// /* SFQRED parameters */
// __u32 limit; /* HARD maximal flow queue length (bytes) */
// __u32 qth_min; /* Min average length threshold (bytes) */
// __u32 qth_max; /* Max average length threshold (bytes) */
// unsigned char Wlog; /* log(W) */
// unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
// unsigned char Scell_log; /* cell size for idle damping */
// unsigned char flags;
// __u32 max_P; /* probability, high resolution */
//
// __u32 limit; /* HARD maximal flow queue length (bytes) */
// __u32 qth_min; /* Min average length threshold (bytes) */
// __u32 qth_max; /* Max average length threshold (bytes) */
// unsigned char Wlog; /* log(W) */
// unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
// unsigned char Scell_log; /* cell size for idle damping */
// unsigned char flags;
// __u32 max_P; /* probability, high resolution */
//
// /* SFQRED stats */
// struct tc_sfqred_stats stats;
// };
//
// struct tc_sfqred_stats stats;
// };
type TcSfqQoptV1 struct {
TcSfqQopt
Depth uint32
@@ -1117,3 +1185,427 @@ func DeserializeTcSfqQoptV1(b []byte) *TcSfqQoptV1 {
func (x *TcSfqQoptV1) Serialize() []byte {
return (*(*[SizeofTcSfqQoptV1]byte)(unsafe.Pointer(x)))[:]
}
// IPProto represents Flower ip_proto attribute
type IPProto uint8
const (
IPPROTO_TCP IPProto = unix.IPPROTO_TCP
IPPROTO_UDP IPProto = unix.IPPROTO_UDP
IPPROTO_SCTP IPProto = unix.IPPROTO_SCTP
IPPROTO_ICMP IPProto = unix.IPPROTO_ICMP
IPPROTO_ICMPV6 IPProto = unix.IPPROTO_ICMPV6
)
func (i IPProto) Serialize() []byte {
arr := make([]byte, 1)
arr[0] = byte(i)
return arr
}
func (i IPProto) String() string {
switch i {
case IPPROTO_TCP:
return "tcp"
case IPPROTO_UDP:
return "udp"
case IPPROTO_SCTP:
return "sctp"
case IPPROTO_ICMP:
return "icmp"
case IPPROTO_ICMPV6:
return "icmpv6"
}
return fmt.Sprintf("%d", i)
}
const (
MaxOffs = 128
SizeOfPeditSel = 24
SizeOfPeditKey = 24
TCA_PEDIT_KEY_EX_HTYPE = 1
TCA_PEDIT_KEY_EX_CMD = 2
)
const (
TCA_PEDIT_UNSPEC = iota
TCA_PEDIT_TM
TCA_PEDIT_PARMS
TCA_PEDIT_PAD
TCA_PEDIT_PARMS_EX
TCA_PEDIT_KEYS_EX
TCA_PEDIT_KEY_EX
)
// /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It
// * means no specific header type - offset is relative to the network layer
// */
type PeditHeaderType uint16
const (
TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK = iota
TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
__PEDIT_HDR_TYPE_MAX
)
type PeditCmd uint16
const (
TCA_PEDIT_KEY_EX_CMD_SET = 0
TCA_PEDIT_KEY_EX_CMD_ADD = 1
)
type TcPeditSel struct {
TcGen
NKeys uint8
Flags uint8
}
func DeserializeTcPeditKey(b []byte) *TcPeditKey {
return (*TcPeditKey)(unsafe.Pointer(&b[0:SizeOfPeditKey][0]))
}
func DeserializeTcPedit(b []byte) (*TcPeditSel, []TcPeditKey) {
x := &TcPeditSel{}
copy((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(x)))[:SizeOfPeditSel], b)
var keys []TcPeditKey
next := SizeOfPeditKey
var i uint8
for i = 0; i < x.NKeys; i++ {
keys = append(keys, *DeserializeTcPeditKey(b[next:]))
next += SizeOfPeditKey
}
return x, keys
}
type TcPeditKey struct {
Mask uint32
Val uint32
Off uint32
At uint32
OffMask uint32
Shift uint32
}
type TcPeditKeyEx struct {
HeaderType PeditHeaderType
Cmd PeditCmd
}
type TcPedit struct {
Sel TcPeditSel
Keys []TcPeditKey
KeysEx []TcPeditKeyEx
Extend uint8
}
func (p *TcPedit) Encode(parent *RtAttr) {
parent.AddRtAttr(TCA_ACT_KIND, ZeroTerminated("pedit"))
actOpts := parent.AddRtAttr(TCA_ACT_OPTIONS, nil)
bbuf := bytes.NewBuffer(make([]byte, 0, int(unsafe.Sizeof(p.Sel)+unsafe.Sizeof(p.Keys))))
bbuf.Write((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(&p.Sel)))[:])
for i := uint8(0); i < p.Sel.NKeys; i++ {
bbuf.Write((*(*[SizeOfPeditKey]byte)(unsafe.Pointer(&p.Keys[i])))[:])
}
actOpts.AddRtAttr(TCA_PEDIT_PARMS_EX, bbuf.Bytes())
exAttrs := actOpts.AddRtAttr(int(TCA_PEDIT_KEYS_EX|NLA_F_NESTED), nil)
for i := uint8(0); i < p.Sel.NKeys; i++ {
keyAttr := exAttrs.AddRtAttr(int(TCA_PEDIT_KEY_EX|NLA_F_NESTED), nil)
htypeBuf := make([]byte, 2)
cmdBuf := make([]byte, 2)
NativeEndian().PutUint16(htypeBuf, uint16(p.KeysEx[i].HeaderType))
NativeEndian().PutUint16(cmdBuf, uint16(p.KeysEx[i].Cmd))
keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_HTYPE, htypeBuf)
keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_CMD, cmdBuf)
}
}
func (p *TcPedit) SetEthDst(mac net.HardwareAddr) {
u32 := NativeEndian().Uint32(mac)
u16 := NativeEndian().Uint16(mac[4:])
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
tKey.Val = u32
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = uint32(u16)
tKey.Mask = 0xffff0000
tKey.Off = 4
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
func (p *TcPedit) SetEthSrc(mac net.HardwareAddr) {
u16 := NativeEndian().Uint16(mac)
u32 := NativeEndian().Uint32(mac[2:])
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
tKey.Val = uint32(u16) << 16
tKey.Mask = 0x0000ffff
tKey.Off = 4
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Mask = 0
tKey.Off = 8
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
func (p *TcPedit) SetIPv6Src(ip6 net.IP) {
u32 := NativeEndian().Uint32(ip6[:4])
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 8
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
u32 = NativeEndian().Uint32(ip6[4:8])
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 12
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
u32 = NativeEndian().Uint32(ip6[8:12])
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 16
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
u32 = NativeEndian().Uint32(ip6[12:16])
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 20
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
func (p *TcPedit) SetDstIP(ip net.IP) {
if ip.To4() != nil {
p.SetIPv4Dst(ip)
} else {
p.SetIPv6Dst(ip)
}
}
func (p *TcPedit) SetSrcIP(ip net.IP) {
if ip.To4() != nil {
p.SetIPv4Src(ip)
} else {
p.SetIPv6Src(ip)
}
}
func (p *TcPedit) SetIPv6Dst(ip6 net.IP) {
u32 := NativeEndian().Uint32(ip6[:4])
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 24
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
u32 = NativeEndian().Uint32(ip6[4:8])
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 28
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
u32 = NativeEndian().Uint32(ip6[8:12])
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 32
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
u32 = NativeEndian().Uint32(ip6[12:16])
tKey = TcPeditKey{}
tKeyEx = TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 36
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
func (p *TcPedit) SetIPv4Src(ip net.IP) {
u32 := NativeEndian().Uint32(ip[:4])
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 12
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
func (p *TcPedit) SetIPv4Dst(ip net.IP) {
u32 := NativeEndian().Uint32(ip[:4])
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
tKey.Val = u32
tKey.Off = 16
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
// SetDstPort only tcp and udp are supported to set port
func (p *TcPedit) SetDstPort(dstPort uint16, protocol uint8) {
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
switch protocol {
case unix.IPPROTO_TCP:
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
case unix.IPPROTO_UDP:
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
default:
return
}
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
tKey.Val = uint32(Swap16(dstPort)) << 16
tKey.Mask = 0x0000ffff
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}
// SetSrcPort only tcp and udp are supported to set port
func (p *TcPedit) SetSrcPort(srcPort uint16, protocol uint8) {
tKey := TcPeditKey{}
tKeyEx := TcPeditKeyEx{}
switch protocol {
case unix.IPPROTO_TCP:
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP
case unix.IPPROTO_UDP:
tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP
default:
return
}
tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET
tKey.Val = uint32(Swap16(srcPort))
tKey.Mask = 0xffff0000
p.Keys = append(p.Keys, tKey)
p.KeysEx = append(p.KeysEx, tKeyEx)
p.Sel.NKeys++
}

41
vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go generated vendored Normal file
View File

@@ -0,0 +1,41 @@
package nl
const (
VDPA_GENL_NAME = "vdpa"
VDPA_GENL_VERSION = 0x1
)
const (
VDPA_CMD_UNSPEC = iota
VDPA_CMD_MGMTDEV_NEW
VDPA_CMD_MGMTDEV_GET /* can dump */
VDPA_CMD_DEV_NEW
VDPA_CMD_DEV_DEL
VDPA_CMD_DEV_GET /* can dump */
VDPA_CMD_DEV_CONFIG_GET /* can dump */
VDPA_CMD_DEV_VSTATS_GET
)
const (
VDPA_ATTR_UNSPEC = iota
VDPA_ATTR_MGMTDEV_BUS_NAME
VDPA_ATTR_MGMTDEV_DEV_NAME
VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES
VDPA_ATTR_DEV_NAME
VDPA_ATTR_DEV_ID
VDPA_ATTR_DEV_VENDOR_ID
VDPA_ATTR_DEV_MAX_VQS
VDPA_ATTR_DEV_MAX_VQ_SIZE
VDPA_ATTR_DEV_MIN_VQ_SIZE
VDPA_ATTR_DEV_NET_CFG_MACADDR
VDPA_ATTR_DEV_NET_STATUS
VDPA_ATTR_DEV_NET_CFG_MAX_VQP
VDPA_ATTR_DEV_NET_CFG_MTU
VDPA_ATTR_DEV_NEGOTIATED_FEATURES
VDPA_ATTR_DEV_MGMTDEV_MAX_VQS
VDPA_ATTR_DEV_SUPPORTED_FEATURES
VDPA_ATTR_DEV_QUEUE_INDEX
VDPA_ATTR_DEV_VENDOR_ATTR_NAME
VDPA_ATTR_DEV_VENDOR_ATTR_VALUE
VDPA_ATTR_DEV_FEATURES
)

View File

@@ -131,7 +131,15 @@ func (x *XfrmAddress) ToIP() net.IP {
return ip
}
func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet {
// family is only used when x and prefixlen are both 0
func (x *XfrmAddress) ToIPNet(prefixlen uint8, family uint16) *net.IPNet {
empty := [SizeofXfrmAddress]byte{}
if bytes.Equal(x[:], empty[:]) && prefixlen == 0 {
if family == FAMILY_V6 {
return &net.IPNet{IP: net.ParseIP("::"), Mask: net.CIDRMask(int(prefixlen), 128)}
}
return &net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(int(prefixlen), 32)}
}
ip := x.ToIP()
if GetIPFamily(ip) == FAMILY_V4 {
return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)}

View File

@@ -15,6 +15,7 @@ const (
SizeofXfrmEncapTmpl = 0x18
SizeofXfrmUsersaFlush = 0x1
SizeofXfrmReplayStateEsn = 0x18
SizeofXfrmReplayState = 0x0c
)
const (
@@ -28,6 +29,11 @@ const (
XFRM_STATE_ESN = 128
)
const (
XFRM_SA_XFLAG_DONT_ENCAP_DSCP = 1
XFRM_SA_XFLAG_OSEQ_MAY_WRAP = 2
)
// struct xfrm_usersa_id {
// xfrm_address_t daddr;
// __be32 spi;
@@ -103,6 +109,7 @@ func (msg *XfrmStats) Serialize() []byte {
// };
//
// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
// #define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2
//
type XfrmUsersaInfo struct {
@@ -332,3 +339,23 @@ func (msg *XfrmReplayStateEsn) Serialize() []byte {
// We deliberately do not pass Bmp, as it gets set by the kernel.
return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:]
}
// struct xfrm_replay_state {
// __u32 oseq;
// __u32 seq;
// __u32 bitmap;
// };
type XfrmReplayState struct {
OSeq uint32
Seq uint32
BitMap uint32
}
func DeserializeXfrmReplayState(b []byte) *XfrmReplayState {
return (*XfrmReplayState)(unsafe.Pointer(&b[0:SizeofXfrmReplayState][0]))
}
func (msg *XfrmReplayState) Serialize() []byte {
return (*(*[SizeofXfrmReplayState]byte)(unsafe.Pointer(msg)))[:]
}