Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time/timestamp: switch to use the upstreamed funcs in sys/unix #411

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 76 additions & 19 deletions phc/unix/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,33 @@ func IoctlGetHwTstamp(fd int, ifname string) (*HwTstampConfig, error) {
return &value, err
}

// IoctlSetHwTstamp updates the hardware timestamping configuration for
// the network device specified by ifname.
func IoctlSetHwTstamp(fd int, ifname string, cfg *HwTstampConfig) error {
ifr, err := NewIfreq(ifname)
if err != nil {
return err
}
ifrd := ifr.withData(unsafe.Pointer(cfg))
return ioctlIfreqData(fd, SIOCSHWTSTAMP, &ifrd)
}

const (
HWTSTAMP_FILTER_NONE = 0x0 //nolint:revive
HWTSTAMP_FILTER_ALL = 0x1 //nolint:revive
HWTSTAMP_FILTER_SOME = 0x2 //nolint:revive
HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3 //nolint:revive
HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6 //nolint:revive
HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9 //nolint:revive
HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc //nolint:revive
)

const (
HWTSTAMP_TX_OFF = 0x0 //nolint:revive
HWTSTAMP_TX_ON = 0x1 //nolint:revive
HWTSTAMP_TX_ONESTEP_SYNC = 0x2 //nolint:revive
)

// https://go-review.googlesource.com/c/sys/+/619335

// EthtoolTsInfo a struct returned by ETHTOOL_GET_TS_INFO function of
Expand Down Expand Up @@ -93,33 +120,63 @@ func ClockSettime(clockid int32, time *Timespec) (err error) {

// bridging to upstream

type Cmsghdr = unix.Cmsghdr
type Errno = unix.Errno
type Msghdr = unix.Msghdr
type PollFd = unix.PollFd
type RawSockaddrInet4 = unix.RawSockaddrInet4
type Timex = unix.Timex
type SockaddrInet4 = unix.SockaddrInet4
type SockaddrInet6 = unix.SockaddrInet6
type Sockaddr = unix.Sockaddr
type Timespec = unix.Timespec

type Timex = unix.Timex
type Utsname = unix.Utsname

func ByteSliceToString(b []byte) string { return unix.ByteSliceToString(b) }
func ClockAdjtime(c int32, t *Timex) (int, error) { return unix.ClockAdjtime(c, t) }
func Close(fd int) (err error) { return unix.Close(fd) }
func ErrnoName(e syscall.Errno) string { return unix.ErrnoName(e) }
func Poll(f []PollFd, t int) (int, error) { return unix.Poll(f, t) }
func Recvmsg(a int, b, c []byte, d int) (int, int, int, Sockaddr, error) {
return unix.Recvmsg(a, b, c, d)
}
func SetsockoptInt(a, b, c, d int) error { return unix.SetsockoptInt(a, b, c, d) }
func Socket(domain, typ, proto int) (fd int, err error) { return unix.Socket(domain, typ, proto) }
func Close(fd int) (err error) { return unix.Close(fd) }
func Syscall(a, b, c, d uintptr) (uintptr, uintptr, Errno) { return unix.Syscall(a, b, c, d) }
func ByteSliceToString(b []byte) string { return unix.ByteSliceToString(b) }
func ClockAdjtime(c int32, t *Timex) (int, error) { return unix.ClockAdjtime(c, t) }
func TimeToTimespec(t time.Time) (Timespec, error) { return unix.TimeToTimespec(t) }
func Uname(s *Utsname) error { return unix.Uname(s) }

const (
AF_INET = unix.AF_INET //nolint:revive
EAGAIN = unix.EAGAIN //nolint:revive
EINVAL = unix.EINVAL //nolint:revive
ENOENT = unix.ENOENT //nolint:revive
ETHTOOL_GET_TS_INFO = unix.ETHTOOL_GET_TS_INFO //nolint:revive
IFNAMSIZ = unix.IFNAMSIZ //nolint:revive
SIOCETHTOOL = unix.SIOCETHTOOL //nolint:revive
SIOCGHWTSTAMP = unix.SIOCGHWTSTAMP //nolint:revive
SizeofPtr = unix.SizeofPtr
SizeofSockaddrInet4 = unix.SizeofSockaddrInet4
SOCK_DGRAM = unix.SOCK_DGRAM //nolint:revive
SYS_CLOCK_SETTIME = unix.SYS_CLOCK_SETTIME //nolint:revive
SYS_IOCTL = unix.SYS_IOCTL //nolint:revive
TIME_OK = unix.TIME_OK //nolint:revive
AF_INET = unix.AF_INET //nolint:revive
EAGAIN = unix.EAGAIN //nolint:revive
EINVAL = unix.EINVAL //nolint:revive
ENOENT = unix.ENOENT //nolint:revive
ENOTSUP = unix.ENOTSUP //nolint:revive
ETHTOOL_GET_TS_INFO = unix.ETHTOOL_GET_TS_INFO //nolint:revive
IFNAMSIZ = unix.IFNAMSIZ //nolint:revive
MSG_ERRQUEUE = unix.MSG_ERRQUEUE //nolint:revive
POLLERR = unix.POLLERR //nolint:revive
SIOCETHTOOL = unix.SIOCETHTOOL //nolint:revive
SIOCGHWTSTAMP = unix.SIOCGHWTSTAMP //nolint:revive
SIOCSHWTSTAMP = unix.SIOCSHWTSTAMP //nolint:revive
SizeofPtr = unix.SizeofPtr
SizeofSockaddrInet4 = unix.SizeofSockaddrInet4
SOCK_DGRAM = unix.SOCK_DGRAM //nolint:revive
SOF_TIMESTAMPING_OPT_TSONLY = unix.SOF_TIMESTAMPING_OPT_TSONLY //nolint:revive
SOF_TIMESTAMPING_RAW_HARDWARE = unix.SOF_TIMESTAMPING_RAW_HARDWARE //nolint:revive
SOF_TIMESTAMPING_RX_HARDWARE = unix.SOF_TIMESTAMPING_RX_HARDWARE //nolint:revive
SOF_TIMESTAMPING_RX_SOFTWARE = unix.SOF_TIMESTAMPING_RX_SOFTWARE //nolint:revive
SOF_TIMESTAMPING_SOFTWARE = unix.SOF_TIMESTAMPING_SOFTWARE //nolint:revive
SOF_TIMESTAMPING_TX_HARDWARE = unix.SOF_TIMESTAMPING_TX_HARDWARE //nolint:revive
SOF_TIMESTAMPING_TX_SOFTWARE = unix.SOF_TIMESTAMPING_TX_SOFTWARE //nolint:revive
SOL_SOCKET = unix.SOL_SOCKET //nolint:revive
SO_SELECT_ERR_QUEUE = unix.SO_SELECT_ERR_QUEUE //nolint:revive
SO_TIMESTAMPING_NEW = unix.SO_TIMESTAMPING_NEW //nolint:revive
SO_TIMESTAMPING = unix.SO_TIMESTAMPING //nolint:revive
SYS_CLOCK_SETTIME = unix.SYS_CLOCK_SETTIME //nolint:revive
SYS_IOCTL = unix.SYS_IOCTL //nolint:revive
SYS_RECVMSG = unix.SYS_RECVMSG //nolint:revive
TIME_OK = unix.TIME_OK //nolint:revive
)

var (
Expand Down
43 changes: 1 addition & 42 deletions timestamp/timestamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,7 @@ import (
"net/netip"
"time"

"golang.org/x/sys/unix"
)

// from include/uapi/linux/net_tstamp.h
const (
// HWTSTAMP_TX_ON int 1
hwtstampTXON int32 = 0x00000001
// HWTSTAMP_FILTER_ALL int 1
hwtstampFilterAll int32 = 0x00000001
//HWTSTAMP_FILTER_PTP_V2_L4_EVENT int 6
hwtstampFilterPTPv2L4Event int32 = 0x00000006
"github.com/facebook/time/phc/unix" // a temporary shim for "golang.org/x/sys/unix" until v0.27.0 is cut
)

const (
Expand Down Expand Up @@ -122,37 +112,6 @@ func (t *Timestamp) Type() string {
return "timestamp"
}

// EthtoolGetTSInfo is get time stamping and PHC info command
const EthtoolGetTSInfo uint32 = 0x00000041

// Ifreq is a struct for ioctl ethernet manipulation syscalls.
type ifreq struct {
name [unix.IFNAMSIZ]byte
data uintptr
}

// from include/uapi/linux/net_tstamp.h
type hwtstampConfig struct {
flags int32
txType int32
rxFilter int32
}

// from include/uapi/linux/ethtool.h struct ethtool_ts_info
type hwtstampCaps struct {
cmd uint32
sofTimestamping uint32 /* SOF_TIMESTAMPING_* bitmask */
phcIndex int32
txTypes uint32 /* HWTSTAMP_TX_* */
txReserved0 uint32
txReserved1 uint32
txReserved2 uint32
rxFilters uint32 /* HWTSTAMP_FILTER_ */
rxReserved0 uint32
rxReserved1 uint32
rxReserved2 uint32
}

// AttemptsTXTS is configured amount of attempts to read TX timestamp
var AttemptsTXTS = defaultTXTS

Expand Down
55 changes: 22 additions & 33 deletions timestamp/timestamp_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"time"
"unsafe"

"golang.org/x/sys/unix"
"github.com/facebook/time/phc/unix" // a temporary shim for "golang.org/x/sys/unix" until v0.27.0 is cut
)

// unix.Cmsghdr size differs depending on platform
Expand Down Expand Up @@ -85,27 +85,21 @@ func byteToTime(data []byte) (time.Time, error) {
}

func ioctlHWTimestampCaps(fd int, ifname string) (int32, int32, error) {
// empty config, will be populated after we call SIOCETHTOOL
hw := &hwtstampCaps{
cmd: EthtoolGetTSInfo,
}
var rxFilter int32
var txFilter int32
var rxFilter, txFilter int32

i := &ifreq{data: uintptr(unsafe.Pointer(hw))}
copy(i.name[:unix.IFNAMSIZ-1], ifname)
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), unix.SIOCETHTOOL, uintptr(unsafe.Pointer(i))); errno != 0 {
return rxFilter, txFilter, fmt.Errorf("failed to run ioctl SIOCETHTOOL to see what is supported: %s (%w)", unix.ErrnoName(errno), errno)
hw, err := unix.IoctlGetEthtoolTsInfo(fd, ifname)
if err != nil {
return 0, 0, fmt.Errorf("failed to run ioctl SIOCETHTOOL to see what is supported: (%w)", err)
}

if hw.txTypes&(1<<hwtstampTXON) > 0 {
txFilter = hwtstampTXON
if hw.Tx_types&(1<<unix.HWTSTAMP_TX_ON) > 0 {
txFilter = unix.HWTSTAMP_TX_ON
}

if hw.rxFilters&(1<<hwtstampFilterPTPv2L4Event) > 0 {
rxFilter = hwtstampFilterPTPv2L4Event
} else if hw.rxFilters&(1<<hwtstampFilterAll) > 0 {
rxFilter = hwtstampFilterAll
if hw.Rx_filters&(1<<unix.HWTSTAMP_FILTER_PTP_V2_L4_EVENT) > 0 {
rxFilter = unix.HWTSTAMP_FILTER_PTP_V2_L4_EVENT
} else if hw.Rx_filters&(1<<unix.HWTSTAMP_FILTER_ALL) > 0 {
rxFilter = unix.HWTSTAMP_FILTER_ALL
}

if txFilter == 0 || rxFilter == 0 {
Expand All @@ -115,28 +109,23 @@ func ioctlHWTimestampCaps(fd int, ifname string) (int32, int32, error) {
}

func ioctlTimestamp(fd int, ifname string, filter int32) error {
// empty config, will be populated after we call SIOCGHWTSTAMP
hw := &hwtstampConfig{
flags: 0,
txType: 0,
rxFilter: 0,
}

i := &ifreq{data: uintptr(unsafe.Pointer(hw))}
copy(i.name[:unix.IFNAMSIZ-1], ifname)
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), unix.SIOCGHWTSTAMP, uintptr(unsafe.Pointer(i))); errno != 0 && errno != unix.ENOTSUP {
return fmt.Errorf("failed to run ioctl SIOCGHWTSTAMP to see what is enabled: %s (%w)", unix.ErrnoName(errno), errno)
hw, err := unix.IoctlGetHwTstamp(fd, ifname)
if errors.Is(err, unix.ENOTSUP) {
// for the loopback interface
hw = &unix.HwTstampConfig{}
} else if err != nil {
return fmt.Errorf("failed to run ioctl SIOCGHWTSTAMP to see what is enabled: %w", err)
}

// now check if it matches what we want
if hw.txType == hwtstampTXON && hw.rxFilter == filter {
if hw.Tx_type == unix.HWTSTAMP_TX_ON && hw.Rx_filter == filter {
return nil
}
// set to desired values
hw.txType = hwtstampTXON
hw.rxFilter = filter
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), unix.SIOCSHWTSTAMP, uintptr(unsafe.Pointer(i))); errno != 0 {
return fmt.Errorf("failed to run ioctl SIOCSHWTSTAMP to set timestamps enabled: %s (%w)", unix.ErrnoName(errno), errno)
hw.Tx_type = unix.HWTSTAMP_TX_ON
hw.Rx_filter = filter
if err := unix.IoctlSetHwTstamp(fd, ifname, hw); err != nil {
return fmt.Errorf("failed to run ioctl SIOCSHWTSTAMP to set timestamps enabled: %w", err)
}
return nil
}
Expand Down
Loading